#javascript
Вопрос:
Эй, в последнее время я читал спецификацию ecmascript, и я столкнулся с разговором о лексической среде и переменной среде
Нравится
- Пусть oldEnv-это лексическая среда контекста выполняемого выполнения.
- Пусть blockEnv-это новая объявленная среда(oldEnv).
- Выполните установку объявления о блокировке(StatementList, blockEnv).
- Задайте для лексической среды контекста выполняемого выполнения значение blockEnv.
- Пусть значение blockValue является результатом оценки StatementList.
- Установите для лексической среды контекста выполняемого выполнения значение oldEnv.
- Возвращаемое значение блока.
правильно, лексическая среда теперь указывает на блокенв, который является декларативной записью среды
но это не говорит о том, в каком месте мы ищем переменные.
основываясь на логике, я предполагаю, что это поиск внутри лексической среды.
я спрашиваю, где я могу найти правило, в котором указано место, где мы ищем переменные и функции.
Ответ №1:
Цепочка областей реализуется с помощью свойства [[OuterEnv]] объектов среды.
Каждая запись среды содержит поле [[OuterEnv]], которое либо равно нулю, либо является ссылкой на запись внешней среды. Это используется для моделирования логической вложенности значений записей среды. Внешняя ссылка на (внутреннюю) запись среды-это ссылка на Запись среды, которая логически окружает запись внутренней среды.
В принципе, при поиске привязки для идентификатора используется текущий объект среды, и если соответствующая привязка не найдена, используется привязка, связанная через [[OuterEnv]], и так далее.
Вы можете видеть это в ResolveBinding, который использует GetIdentifierReference. Если GetIdentiferReference on не находит привязки к объекту среды, с которым он вызывается, он рекурсивно вызывает себя с помощью [[OuterEnv]]этой среды:
- Если env имеет значение null, то
- Верните ссылочную запись { [[База]]: неразрешимая, [[Имя ссылки]]: имя, [[Строгое]]: строгое, [[Значение]]: пустое }.
- Пусть будет так ? зав.Имеет привязку(имя).
- Если сущее истинно, то
- Верните ссылочную запись { [[База]]: env, [[Имя ссылки]]: имя, [[Строгое]]: строгое, [[Значение]]: пустое }.
- Ещё,
- Пусть внешнее будет завистью.[[Внешний вид]].
- Вернуться ? GetIdentifierReference(внешний, имя, строгий).
В комментарии вы спросили, зачем нам нужна переменная среда. У нас есть как переменная среда, так и лексическая среда (и глобальная среда, если на то пошло), которые являются объектами записи среды (1, 2). Нам нужна переменная среда по сравнению с лексической средой, чтобы обрабатывать var
объявления с областью действия иначе , чем объявления с лексической областью let
действия ( const
, и т.д.). Например:
function example() {
// Here, the LexicalEnvironment and the VariableEnvironment
// are the same environment record; let's call it "outer"
var a = 1; // Created in "outer"
{
// Here, there's a new environment set as the LexicalEnvironment,
// using "outer" as its [[OuterEnv]. Let's call it "inner". See
// https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation
var b = 2; // Created in "outer"
let c = 3; // Created in "inner"
console.log(typeof a); // "number", found in "outer"
console.log(typeof b); // "number", found in "outer"
console.log(typeof c); // "number", found in "inner"
}
console.log(typeof a); // "number", found in "outer"
console.log(typeof b); // "number", found in "outer"
console.log(typeof c); // "undefined", not found at all
}
example();
Комментарии:
1. так зачем же нам переменная среда, если все работы выполняются с лексической средой. когда мы заглянем внутрь переменной среды ?
2. @AngryJohn — Переменные среды-это записи среды, они просто не единственные. (У меня не должно было быть «лексического» в моем первом абзаце.) Нам нужна переменная среда, отличная от лексической среды , для обработки
var
деклараций с областью действия, отличной от деклараций с лексической областью (let
,const
и т. Д.) (И для старогоwith
оператора).3. @AngryJohn — Я добавил пример, который, я думаю, поможет.
4. Да, но если в начале файл и пять являются одной и той же записью среды, зачем нам нужна копия ? да, когда мы вызовем пример функции, будет создан новый файл, который будет указывать на функцию ER. и все переменные в этой функции будут перенесены в эту функцию ER, и когда мы достигнем блока в вашем примере, будет создан новый файл, и теперь файл будет указывать на этот файл. новый DER[[OuterEnv]] будет указан на старый Env, который в данном случае является функцией ER. после того, как мы дойдем до конца блока, файл будет указан обратно на функцию ER, так в чем же смысл этого VE.
5. кстати, извините, если мой английский звучит так, как будто говорит 6-летний ребенок. английский не мой родной язык (: