Оператор with
не создает полностью новую лексическую область, он просто вводит объект перед цепочкой областей действия, например, если вы захватите переменную i
, он будет работать :
for (var i = 1; i <= 5; i++) {
with({x:i}) {
document.getElementById('link' + i).onclick = function() {
alert(x);
return false;
};
}
}
Позвольте мне попытаться объяснить это лучше на другом примере:
var x = 10, y = 10; // Step 1
with ({x: 20}) { // Step 2
var x = 30, y = 30; // Step 3
alert(x); // 30
alert(y); // 30
}
alert(x); // 10
alert(y); // 30
На шаге 1 объявляются переменные x
и y
, которые являются частью первого объекта в цепочке областей действия, глобального объекта.
На шаге 2 новый объект ({x:20}
) вводится в цепочку областей действия с помощью оператора with
, теперь цепочка областей действия выглядит примерно так:
________ ________
| x = 10 | <--------- | x = 20 |
| y = 10 | ¯¯¯¯¯¯¯¯¯
¯¯¯¯¯¯¯¯
На шаге 3 выполняется еще один оператор var
, но он не действует, потому что, как я уже говорил, только функции создают полную лексическую область действия.
Оператор var
не имеет эффекта, но назначение имеет значение, поэтому, когда переменная x
разрешена, достигается первый объект в цепочке областей действия, который мы ввели с помощью with
.
Идентификатор y
также разрешен, но он не найден в первом объекте в цепочке, поэтому поиск продолжается и находит его в последнем объекте, цепочке областей после назначений выглядит так:
________ ________
| x = 10 | <--------- | <b>x = 30</b> |
| <b>y = 30</b> | ¯¯¯¯¯¯¯¯¯
¯¯¯¯¯¯¯¯
Когда оператор with
заканчивается, цепочка областей действия наконец восстанавливается:
________
| x = 10 |
| y = 30 |
¯¯¯¯¯¯¯¯
Edit:
Позвольте мне немного расширить и поговорить о функциях.
При создании функции ее текущая родительская область привязывается, например:
var fn;
// augment scope chain
with ({foo: "bar"}) {
fn = function () { // create function
return foo;
};
}
// restored scope chain
fn(); // "bar", foo is still accessible inside fn
Новая лексическая область создается и добавляется в цепочку областей при выполнении функции.
В основном все идентификаторы (имена) аргументов функций, переменных, объявленных с помощью var
, и функций, объявленных с помощью оператора function
, связаны как свойства нового объекта, созданного за сценой, непосредственно перед выполнением самой функции (когда элементы управления входят в этот новый контекст выполнения ).
Этот объект не доступен через код, называется Переменная объект , например:
var x = 10, y = 10; // Step 1
(function () { // Step 2
var x, y;
x = 30; // Step 4
y = 30;
alert(x); // 30
alert(y); // 30
})(); // Step 3
alert(x); // 10 // Step 5
alert(y); // 10
На шаге 1, как и в первом примере, объявляются переменные x
и y
, и они являются частью первого объекта в цепочке областей действия, глобального объекта.
На шаге 2 создается новый объект функции, родительский контекст которого в этот момент сохраняется в [[Scope]] этой функции, содержащей теперь x
и y
.
На шаге 3 вызывается функция, запускающая процесс Variable Instantiation , который создает новый объект в цепочке областей действия, содержащий локальные переменные x
и y
, объявленные внутри этого Новая функция, цепочка областей видимости в данный момент выглядит следующим образом:
parent scope Variable Object
________ _______________
| x = 10 | <--------- | x = undefined |
| y = 10 | | y = undefined |
¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Затем на шаге 4 выполняется присвоение x
и y
, но поскольку новая лексическая область видимости создана, это не влияет на внешние значения.
parent scope Variable Object
________ ________
| x = 10 | <--------- | x = <b>30</b> |
| y = 10 | | y = <b>30</b> |
¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯
И, наконец, на шаге 5 функция заканчивается, и цепочка областей действия возвращается в исходное состояние.
________
| x = 10 |
| y = 10 |
¯¯¯¯¯¯¯¯
Рекомендуемые лекции: