Как let и const вписываются в текущий контекст выполнения? Они каждый раз создают новый? - PullRequest
1 голос
/ 25 апреля 2020

Итак, я читал некоторые вещи о замыканиях, областях видимости, лексической среде и контексте выполнения. Насколько я понимаю, текущий контекст выполнения имеет лексическую среду и переменную среду (которая, по-видимому, является специфическим типом лексической среды c при чтении других потоков при переполнении стека и о которой я упоминал в ECMAScript 2016, но не определил). Переменная среда имеет идентификаторы, которые были объявлены с помощью var, и значения, связанные с ними. Где-то в своей записи лексическая среда имеет привязки и значения переменных, объявленные с помощью let и const. У меня есть несколько вопросов, связанных с этим, однако.

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

Кроме того, где в этой картине вписываются замыкания и области видимости? Из того, что я понимаю, область видимости - это только то, что доступно текущему контексту выполнения, но это просто идея того, что доступно, или определение области действия также включает способ JavaScript поиска переменной, изучения текущей лексической среды и переменная среда и последующие среды в цепочке областей? Что касается замыканий, MDN определяет замыкание как «комбинацию функции, объединенной вместе (вложенной) со ссылками на ее окружающее состояние (лексическое окружение)», и я вижу, что она использовалась несколько раз в ECMAScript 2016 - это замыкания только начало нового контекст выполнения, поскольку они определяют лексическую среду (как насчет переменной среды) и «содержат» функцию?

Наконец, где хранятся переменные с let и const в текущем контексте выполнения? В нескольких потоках Stack Overflow я видел, что они находятся в лексической среде (от поиска в Google я ничего не смог найти), в частности, первый ответ здесь ( Где хранятся глобальные переменные let? ) говорит что «Поскольку вы использовали let, а не var, он сохраняется в записи декларативной среды, связанной с глобальным объектом лексической среды, а не с самим глобальным объектом». и я предполагаю, что это то же самое в целом. Как насчет этой ситуации:

function foo() {
    let a = 1;
    {
        let a = 2;
        console.log(a)
    }
    console.log(a)
}

foo()

Что здесь происходит - две переменные с именем "a" не могут находиться в одной лексической среде, верно? Итак, есть две лексические среды, но как создается вторая. Создается ли новый контекст выполнения в начале нового блока? Это происходит для каждого блока или только для тех, которые имеют новые переменные, объявленные с помощью let и const?

Извините за все вопросы, но мой главный - последний, и я не понимаю основы для его понимания, Вот почему я задал все вопросы. Спасибо за ваше время.

1 Ответ

0 голосов
/ 25 апреля 2020

Несколько вопросов здесь, на самом деле.

MDN определяет замыкание как:

Закрытие - это комбинация функции, объединенной вместе (прилагается) с ссылки на его окружающее состояние (лексическое окружение). Другими словами, замыкание дает вам доступ к области видимости внешней функции из внутренней функции. В JavaScript замыкания создаются каждый раз при создании функции во время создания функции.

Надеемся, что раздел «другими словами» здесь помогает понять, что подразумевается под «лексической средой».

В отличие от этого let и const ограничены блоком. From MDN :

let позволяет объявлять переменные, ограниченные областью действия оператора блока или выражения, в котором он используется, в отличие от ключевого слова var, которое определяет переменная глобально или локально для всей функции независимо от области видимости блока. ...

Таким образом, это в основном то же самое, за исключением того, что область действия является уровнем блока, а не уровнем функции.

Разница между "глобальным объектом лексической среды" и "глобальным объектом" "

Глобальный объект в основном означает, что глобальная переменная добавляется как свойство к window объекту. Обратите внимание на разницу в этом примере (при условии, что этот код выполняется в глобальной области, а не в функции):

let t = 4;
console.log(t, window.t); // window.t will be undefined
// --> 4, undefined

var q = 4;
console.log(q, window.q); // window.q will equal the global q
// --> 4, 4

две переменные с именем "a" не могут находиться в одной лексической среде?

* Редактировать: после некоторого прочтения я обнаружил, что то, что я думал о лексических средах, было не очень точным. Глядя на спецификации ecma-262 , это, кажется, проливает некоторый свет на предмет:

Лексическое окружение состоит из Записи окружения и, возможно, нулевой ссылки на внешний Лексический Окружающая обстановка. Обычно лексическая среда связана с некоторой определенной c syntacti c структурой кода ECMAScript, такой как FunctionDeclaration, BlockStatement или предложение Catch для TryStatement, и новая Лексическая среда создается каждый раз, когда такой код оценивается.

Так что кажется относительно уверенным, что блок в вашем примере получает свою собственную лексическую среду со ссылкой / указателем на внешнюю лексическую среду тела функции и т. Д.

Раздел ecma specs , в котором говорится о let и const, также делает интересное различие:

Переменные создаются, когда создается их содержащая Lexical Environment, но может к нему нельзя получить доступ, пока не будет оценена переменная LexicalBinding.

Переменная окружение

При просмотре раздела spe c по контекстам выполнения , It показывает, что контекст выполнения включает в себя компонент с именем VariableEnvir onment:

Идентифицирует лексическую среду, среда EnvironmentRecord которой содержит привязки, созданные VariableStatements в этом контексте выполнения.

Итак, это вторая лексическая среда, которая имеет спецификацию c цель. Чтобы выяснить, что это за специальное назначение, давайте посмотрим, что такое Запись среды :

Декларативные записи среды используются для определения эффекта элементов syntacti c языка ECMAScript. как предложения FunctionDeclarations, VariableDeclarations и Catch, которые напрямую связывают привязки идентификаторов со значениями языка ECMAScript. Записи среды объекта используются для определения эффекта элементов ECMAScript, таких как WithStatement, которые связывают привязки идентификаторов со свойствами некоторого объекта.

Некоторые вещи, кажется, выпрыгивают. В нем говорится о catch предложениях и with предложениях.

  • Предложения Catch кажутся странным исключением, обсуждаемым в спецификации c, приложение B.3.5 VariableStatements в блоках Catch . Здесь обсуждаются изменения в поведении объявлений переменных.
  • С операторами также являются странными утками, поскольку они позволяют ссылаться на свойства объекта, как если бы они были локальными переменными.

Я предполагаю, что здесь немного, но это выглядит для меня как это свойство VariableEnvironment контекста выполнения - это вторая лексическая среда, предназначенная для работы со странными вещами, которые действуют как локальные переменные, но на самом деле это не так.

...