Как именно выполняется привязка в замыканиях?

function f() { return s; } // works fine though no `s` is defined yet !

var s=1;
f(); // 1

delete s;

var s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

во-первых, вы можете закрыть переменную (s), которая еще не определена. Как это возможно, если используется лексическая (статическая) область видимости?

во-вторых, после удаления исходного s f() может найти новый s. Означает ли это, что замыкания привязаны к именам переменных, а не к ссылкам или индексам таблицы символов или к чему-то более машинному? Я ожидаю, что закрытие лексической области видимости вызовет ошибку, поскольку исходный sудален. Новый s просто повторно использует имя и не имеет ничего общего с исходным s.

И в-третьих, s внутри области анонимной функции не используется f(), значит ли это, что лексическая область видимости действительно задействована?


person Ashkan Kh. Nazary    schedule 29.03.2013    source источник
comment
Я думаю, мы можем ответить на любой вопрос о закрытии с помощью подъема, даже не читая их.   -  person georg    schedule 29.03.2013
comment
Возможно, вам будет полезно попробовать два варианта: во-первых, поместить этот код во IIFE — (function() { ...code... })();. Затем попробуйте исходный код, за исключением оператора "use strict"; (только эта строковая константа) в самом верху.   -  person Pointy    schedule 29.03.2013
comment
(На самом деле модификация "use strict";, вероятно, самая интересная.) В любом случае, да, все дело в лексической области видимости.   -  person Pointy    schedule 29.03.2013
comment
упс, на самом деле в строгом режиме оператор delete просто не будет работать.   -  person Pointy    schedule 29.03.2013


Ответы (2)


Этот пример эквивалентен

var s;
function f() { return s; } // works fine though no `s` is defined yet !

s=1;
f(); // 1

delete s;

s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

Объявления переменных Javascript поднимаются наверх своей области видимости и затем объявляются. Затем они определяются там, где их устанавливает пользователь. Таким образом, вы можете ссылаться на переменную javascript до ее объявления в области действия функции.

Также обратите внимание, что delete обычно используется для свойств объекта, а не объекта, объявленного с помощью var. Удаление в этом случае не имеет никакого эффекта, независимо от закрытия. См. скрипку здесь: jsfiddle

person Ben McCormick    schedule 29.03.2013

во-первых, вы можете закрыть переменную (переменные), которая еще не определена... как это возможно, если используется лексическая (статическая) область видимости?

См. подъем

во-вторых, после удаления исходных s функция f() может найти новые s. Означает ли это, что замыкания привязаны к именам переменных, а не к ссылкам или индексам таблицы символов или к чему-то более машинному? Я ожидаю, что закрытие лексической области видимости выдаст ошибку, поскольку исходный s — это delete. Новый s просто повторно использует имя и не имеет ничего общего с исходным s.

Новостей нет, все объявления подняты. В конце только одна буква s. Подъем по-прежнему применяется.

и в-третьих, s внутри области действия анонимной функции не используется f(), значит ли это, что лексическая область видимости действительно задействована?

Да, s внутри анонимной функции является для нее локальным, и в данном случае замыкание формируется над глобальным s.

person Johnbabu Koppolu    schedule 29.03.2013
comment
Я думаю, что второе на самом деле связано с тем, что delete s не имеет эффектов, а не с подъемом, как показано на jsfiddle.net/F5xDz - person Ashkan Kh. Nazary; 29.03.2013