У вас есть два вопроса здесь.В будущем вы можете рассмотреть возможность публикации двух отдельных вопросов, когда у вас есть два вопроса.
При создании замыкания в Javascript все переменные в области действия во время создания замыкания «заключены» в него?
Вы не указываете, о какой из версий «JavaScript» вы говорите.Я предполагаю, что вы говорите о правильной реализации языка ECMAScript 3.Если вы говорите о какой-то другой версии «JavaScript», скажите, о какой вы говорите.
В ECMAScript 5 обновлены правила работы лексических сред и "eval".Я не являюсь членом Технического комитета 39 с 2001 года, и я не следил за последними изменениями в спецификации ECMAScript 5;если вы хотите получить ответ в контексте последних правил ECMAScript 5, найдите эксперта по этой спецификации;Я не тот.
Ответ на ваш вопрос в контексте ECMAScript 3: да .Спецификация ECMAScript 3 очень ясна в этом вопросе, но вам не нужно смотреть на эту спецификацию, чтобы знать, что это должно быть так:
function f()
{
var referenced = 1;
var notReferenced = 2;
var func = function ()
{
alert(referenced);
alert(eval("notReferenced"));
}
return func;
}
f()();
Как может "eval" работать правильно, если "notReferenced""не перехвачено?
Это все объясняется в спецификации ECMAScript, но я могу кратко подытожить это здесь.
Каждая переменная связана с" переменным объектом ", который является объектому которого есть свойства, имена которых являются именами переменных. переменный объект для функции f идентичен активационному объекту из f - то есть объекту, который магически создается каждый раз, когда вызывается f.Переменный объект имеет три свойства: «referenced», «notReferenced» и «func».
Существует переменный объект, называемый «глобальным объектом», который представляет код вне любой функции.Он имеет свойство "f".
Каждый контекст выполнения имеет цепочку областей действия , представляющую собой список объектов, свойства которых ищутся при попытке оценить идентификатор.
С каждым объектом функции связана цепочка областей действия, которая является копией цепочки областей действия, которая действовала при создании функции.
Цепочка области действия, связанная с "f", имеет видглобальный объект.
Когда выполнение вводит "f", текущая цепочка контекста контекста выполнения имеет объект активации "f", помещенный в него.
Когда "f" создает функциюобъект, назначенный "func", связанная с ним цепочка областей действия является копией текущей цепочки областей действия контекста выполнения, то есть цепочки областей действия, содержащей активацию "f", и глобального объекта.
ОК, теперь все объекты настроены правильно.f возвращает func, который затем вызывается.Это создает объект активации для этой функции.Цепочка контекста контекста выполнения выбирается из объекта функции - помните, что это объект активации "f" плюс глобальный объект - и в эту копию цепочки контекста мы помещаем текущий объект активации.Поскольку анонимная функция, которую мы сейчас выполняем, не имеет ни аргументов, ни локальных параметров, это, по сути, запрет.
Затем мы попытаемся оценить «предупреждение»;мы ищем цепочку прицелов.Текущая активация и активация "f" не имеют ничего, называемого "предупреждением", поэтому мы запрашиваем глобальный объект, и он говорит "да", предупреждение - это функция.Затем мы оцениваем «ссылки».Он не на текущем объекте активации, но на объекте активации f, поэтому мы выбираем его значение и передаем его в оповещение.
То же самое в следующей строке.Глобальный объект сообщает нам, что существуют методы «alert» и «eval».Но, конечно, «Эвал» особенный. Eval получает копию текущей цепочки областей видимости, а также строковый аргумент .Eval анализирует строку как программу и затем выполняет программу, используя текущую цепочку областей видимости.Эта программа ищет «notReferenced» и находит его, потому что она находится в текущей цепочке областей действия.
Если у вас есть дополнительные вопросы по этой области, тогда я рекомендую вам прочитать главы 10 и 13 спецификации ECMAScript 3, пока вы не полностью не поймете их.
Давайте более внимательно посмотрим на ваш вопрос:
При создании замыкания в Javascript все переменные в области действия во время создания замыкания"заключены" в него?
Чтобы окончательно ответить на этот вопрос, вам нужно точно сказать нам, что вы подразумеваете под «замыканием» - спецификация ECMAScript 3 нигде не определяет этот термин. Под «замыканием» подразумевается объект функции или цепочка областей действия, захваченная объектом функции ?
Помните, что все эти объекты являются изменяемыми - сама цепочка областей не изменчива, но каждый объект в цепочке изменчив! Существовала или нет переменная «во время» создания либо цепочки областей действия, либо объекта функции, на самом деле немного не имеет значения; переменные приходят, переменные уходят.
Например, переменные, которые еще не были созданы на момент создания объекта функции , могут быть захвачены!
function f()
{
var func = function ()
{
alert(newlyCreated);
}
eval("var newlyCreated = 123;");
return func;
}
f()();
Очевидно, что "newCreated" не является переменной в то время, когда объект функции создается , поскольку он создается после объекта функции. Но когда вызывается функциональный объект, он появляется на объекте активации / переменной f.
Аналогично, переменная, которая существует во время создания вложенного функционального объекта, может быть удалена к моменту выполнения функционального объекта.