renovations
This commit is contained in:
parent
c7d4c7e3ff
commit
e1948130f6
170 changed files with 1496 additions and 1161 deletions
|
@ -5,35 +5,16 @@
|
|||
|
||||
Есть одно исключение из общего правила присвоения `[[Scope]]`, которое мы рассматривали в предыдущей главе.
|
||||
|
||||
**При создании функции с использованием `new Function`, её свойство `[[Scope]]` ссылается не на текущий `LexicalEnvironment`, а на `window`.**
|
||||
При создании функции с использованием `new Function`, её свойство `[[Scope]]` ссылается не на текущий `LexicalEnvironment`, а на `window`.
|
||||
|
||||
## Пример
|
||||
|
||||
Следующий пример демонстрирует как функция, созданная `new Function`, игнорирует внешнюю переменную `a` и выводит глобальную вместо нее.
|
||||
|
||||
Сначала обычное поведение:
|
||||
Следующий пример демонстрирует как функция, созданная `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;
|
||||
|
||||
|
@ -47,19 +28,41 @@ function getFunc() {
|
|||
getFunc()(); // *!*1*/!*, из window
|
||||
```
|
||||
|
||||
Сравним с обычным поведением:
|
||||
|
||||
```js
|
||||
//+ run untrusted refresh
|
||||
var a = 1;
|
||||
|
||||
function getFunc() {
|
||||
var a = 2;
|
||||
|
||||
*!*
|
||||
var func = function() { alert(a); };
|
||||
*/!*
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
getFunc()(); // *!*2*/!*, из LexicalEnvironment функции getFunc
|
||||
```
|
||||
|
||||
|
||||
## Почему так сделано?
|
||||
|
||||
[warn header="Продвинутые знания"]
|
||||
Содержимое этой секции содержит информацию теоретического характера, которая прямо сейчас не обязательна для дальнейшего изучения JavaScript.
|
||||
Содержимое этой секции содержит продвинутую информацию теоретического характера, которая прямо сейчас не обязательна для дальнейшего изучения JavaScript.
|
||||
[/warn]
|
||||
|
||||
**Эта особенность `new Function`, хоть и выглядит странно, на самом деле весьма полезна.**
|
||||
Эта особенность `new Function`, хоть и выглядит странно, на самом деле весьма полезна.
|
||||
|
||||
Представьте себе, что нам действительно нужно создать функцию из строки кода. Наверняка код этой функции неизвестен на момент написания скрипта (иначе зачем `new Function`), но станет известен позже, например получен с сервера или из других источников данных.
|
||||
Представьте себе, что нам действительно нужно создать функцию из строки кода. Текст кода этой функции неизвестен на момент написания скрипта (иначе зачем `new Function`), но станет известен позже, например получен с сервера или из других источников данных.
|
||||
|
||||
При выполнении кода на боевом сервере он наверняка сжат минификатором -- специальной программой, которая уменьшает размер кода, убирая из него лишние комментарии, пробелы, что очень важно -- переименовывает локальные переменные на более короткие.
|
||||
Предположим, что этому коду надо будет взаимодействовать с внешними переменными основного скрипта.
|
||||
|
||||
То есть, обычно если внутри функции есть `var userName`, то минификатор заменит её на `var u` (или другую букву, чтобы не было конфликта), предполагая, что так как переменная видна только внутри функции, то этого всё равно никто не заметит, а код станет короче. И обычно проблем нет.
|
||||
Но проблема в том, что JavaScript при выкладывании на "боевой сервер" предварительно сжимается минификатором -- специальной программой, которая уменьшает размер кода, убирая из него лишние комментарии, пробелы, что очень важно -- переименовывает локальные переменные на более короткие.
|
||||
|
||||
То есть, если внутри функции есть `var userName`, то минификатор заменит её на `var a` (или другую букву, чтобы не было конфликта), предполагая, что так как переменная видна только внутри функции, то этого всё равно никто не заметит, а код станет короче. И обычно проблем нет.
|
||||
|
||||
...Но если бы `new Function` могла обращаться к внешним переменным, то при попытке доступа к `userName` в сжатом коде была бы ошибка, так как минификатор переименовал её.
|
||||
|
||||
|
@ -67,7 +70,7 @@ getFunc()(); // *!*1*/!*, из window
|
|||
|
||||
Описанная особенность `new Function` просто-таки спасает нас от ошибок.
|
||||
|
||||
Если внутри функции, создаваемой через `new Function`, всё же нужно использовать локальные переменные -- нужно всего лишь предусмотреть соответствующие параметры и передавать их явным образом, например так:
|
||||
Ну а если внутри функции, создаваемой через `new Function`, всё же нужно использовать какие-то данные -- без проблем, нужно всего лишь предусмотреть соответствующие параметры и передавать их явным образом, например так:
|
||||
|
||||
```js
|
||||
//+ run untrusted refresh
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue