Сообщение от Riim
|
если внутри этой функции создать переменную, одноименную с той, что запомнена, то она как бы экранируется
|
Да, "экранируется", на этом принципе и работает Scope chain.
Т.е. одноимённые переменные (а также, декларации функций и формальные параметры) более глубокого контекста,
разрешаются (определяются) раньше, чем переменные с тем же именем, но в контексте выше. Цепь областей видимости контекста (Scope chain) при нахождении в коде переменной, опрашивается интерпретатором от самого глубого звена цепи вверх до глобального объекта (и, в некоторых реализациях, прототипа глобального объекта).
var a = 10;
function A() {
var a = 20;
function B() {
var a = 30;
alert(a); // найдено сразу в AO(контекста B)
}
}
Если бы переменная "а" была объявлена один раз (глобально), то при
alert(a) из внутренней функции "B", она бы разрешалась по цепи (Scope chain контекста функции "B"):
1. AO(контекста "B") - (нет) ->
2. AO(контекста "А") - (нет) ->
3. VO(Global) === Global - (да) - 10
Сообщение от Riim
|
теперь если экранируется все запомненное за счет имен аргументов, то хранится ли в памяти внешняя функция
|
Вообще, теоретически, функцию до создания можно распарсить и посмотреть, используются ли в ней свободные переменные, если нет, то, по идее, можно не создавать замыкание. Но в стандарте об этом ничего не сказано, это просто мысли.
С другой стороны, одна вложенная функция может не иметь свободных переменных, а вложенная во вложенную может, поэтому, надо запоминать всегда, получается:
function A() {
var a = 10;
function B() { // нужен ли этой функции Scope A?
function C() {
alert(a); // если B не запомнит Scope A, функция С не найдёт "а"
}
}
}
Но, повторю, по идее, может быть проведена оптимизация на уровне реализации.
Поэтому, все функцию при создании запоминаю лексический контекст (т.е. Scope chain этого контекста), в котором они порождены, отсюда - все функции - замыкания. Функция может быть ни разу не запущена, но [[Scope]] уже в неё записался.
Но, стандарт описывает предложение по оптимизации -
объединённые объекты:
function a() {
function b(z) {
return z * z;
}
return b;
}
var x = a();
var y = a();
Т.к. [[Scope]] функций x и y - не различим (и вообще, оба объекты - не различимы), реализация вправе использовать объединённые объекты в этом случае, или даже - использовать один объект. Поэтому, не всегда внутренняя функция будет создаваться каждый раз разная.