|
Создание функций "на лету"
В JavaScript существует
возможность буквально создавать самим скриптом новые функции. Для этого
используется такой синтаксис:
let func = new
Function([arg1, arg2, ...argN], functionBody);
Функция
создаётся с заданными аргументами arg1...argN и телом functionBody. Например,
создадим функцию для вычисления суммы двух аргументов:
let sumTwo = new Function('a', 'b', 'return a+b;');
Здесь sumTwo ссылается на
созданный объект-функцию, принимающий два аргумента с телом функции «return a+b». Запустим ее и
посмотрим как она будет работать:
console.log( sumTwo(1, 2) );
Да, видим, что
действительно вычисляется сумма от двух аргументов. Получается, что используя new Function() можно
передавать строки с именами аргументов и строку с телом функции, а на выходе получать
готовую функцию. То есть, JavaScript может создавать
сам себя в процессе выполнения. И это иногда используется на практике.
Если нужно
создать функцию без аргументов, то сразу прописывается тело функции:
let hello = new Function('console.log("hello");');
hello();
Надо сказать,
что такое создание функций в процессе исполнения скрипта используется крайне
редко. Один из примеров – прием сложных данных с сервера вместе с функцией,
которая их распаковывает.
Также эти
функции иначе ведут себя при замыканиях. Создадим внутри функции createMsg функцию с
помощью new Function:
function createMsg() {
let msg = "Hello";
return new Function('console.log(msg);');
}
Теперь, при вызове функции createMsg() переменная hello ссылается на
новую созданную функцию, которая выводит в консоль переменную msg:
let hello = createMsg();
hello();
Но в момент
вызова возникает ошибка, связанная с отсутствие переменной msg. Почему так?
Почему замыкание здесь не сработало? Дело в том, что когда функция создаётся с
использованием new Function, она всегда ссылается на глобальное внешнее
окружение, а не на родительское от createMsg. Поэтому такая
функция имеет доступ только к глобальным переменным. И, так как глобальной
переменной msg не существует,
то и возникает такая ошибка.
Если в нашу
программу добавить эту глобальную переменную:
то эта строчка и
будет отображена в консоли.
|