# [[Scope]] для new Function ## Присвоение [[Scope]] для new Function [#scope-Function] Есть одно исключение из общего правила присвоения `[[Scope]]`, которое мы рассматривали в предыдущей главе. **При создании функции с использованием `new Function`, её свойство `[[Scope]]` ссылается не на текущий `LexicalEnvironment`, а на `window`.** ## Пример Следующий пример демонстрирует как функция, созданная `new Function`, игнорирует внешнюю переменную `a` и выводит глобальную вместо нее. Сначала обычное поведение: ```js //+ run untrusted refresh var a = 1; function getFunc() { var a = 2; *!* var func = function() { alert(a); }; */!* return func; } getFunc()(); // *!*2*/!*, из LexicalEnvironment функции getFunc ``` А теперь -- для функции, созданной через `new Function`: ```js //+ run untrusted refresh var a = 1; function getFunc() { var a = 2; *!* var func = new Function('', 'alert(a)'); */!* return func; } getFunc()(); // *!*1*/!*, из window ``` ## Почему так сделано? [warn header="Продвинутые знания"] Содержимое этой секции содержит информацию теоретического характера, которая прямо сейчас не обязательна для дальнейшего изучения JavaScript. [/warn] **Эта особенность `new Function`, хоть и выглядит странно, на самом деле весьма полезна.** Представьте себе, что нам действительно нужно создать функцию из строки кода. Наверняка код этой функции неизвестен на момент написания скрипта (иначе зачем `new Function`), но станет известен позже, например получен с сервера или из других источников данных. При выполнении кода на боевом сервере он наверняка сжат минификатором -- специальной программой, которая уменьшает размер кода, убирая из него лишние комментарии, пробелы, что очень важно -- переименовывает локальные переменные на более короткие. То есть, обычно если внутри функции есть `var userName`, то минификатор заменит её на `var u` (или другую букву, чтобы не было конфликта), предполагая, что так как переменная видна только внутри функции, то этого всё равно никто не заметит, а код станет короче. И обычно проблем нет. ...Но если бы `new Function` могла обращаться к внешним переменным, то при попытке доступа к `userName` в сжатом коде была бы ошибка, так как минификатор переименовал её. **Получается, что даже если бы мы захотели использовать локальные переменные в `new Function`, то после сжатия были бы проблемы, так как минификатор переименовывает локальные переменные.** Описанная особенность `new Function` просто-таки спасает нас от ошибок. Если внутри функции, создаваемой через `new Function`, всё же нужно использовать локальные переменные -- нужно всего лишь предусмотреть соответствующие параметры и передавать их явным образом, например так: ```js //+ run untrusted refresh *!* var sum = new Function('a, b', ' return a + b; '); */!* var a = 1, b = 2; *!* alert( sum(a, b) ); // 3 */!* ``` ## Итого