Позволяют ли операторы создавать свойства глобального объекта?
В JavaScript var
Объявления создают свойства для глобального объекта:
var x = 15;
console.log(window.x); // logs 15 in browser
console.log(global.x); // logs 15 in Node.js
ES6 вводит лексическую область видимости с let
объявления, которые имеют область видимости блока.
let x = 15;
{
let x = 14;
}
console.log(x); // logs 15;
Однако создают ли эти объявления свойства глобального объекта?
let x = 15;
// what is this supposed to log in the browser according to ES6?
console.log(window.x); // 15 in Firefox
console.log(global.x); // undefined in Node.js with flag
2 ответа
Делать
let
операторы создают свойства глобального объекта?
Согласно спецификации, нет:
Глобальная запись среды логически представляет собой одну запись, но она указывается как составная инкапсуляция записи среды объекта и декларативной записи среды. Запись объектной среды имеет в качестве базового объекта глобальный объект связанной области. Этот глобальный объект является значением, возвращаемым записью глобальной среды
GetThisBinding
конкретный метод. Компонент записи объектной среды записи глобальной среды содержит привязки для всех встроенных глобальных переменных ( раздел 18) и все привязки, представленные FunctionDeclaration, GeneratorDeclaration или VariableStatement, содержащимися в глобальном коде. Привязки для всех других объявлений ECMAScript в глобальном коде содержатся в компоненте записи декларативной среды записи глобальной среды.
Еще несколько объяснений:
Декларативная запись среды хранит привязки во внутренней структуре данных. Невозможно каким-либо образом овладеть этой структурой данных (подумайте о сфере действия функции).
Запись окружения объекта использует фактический объект JS в качестве структуры данных. Каждое свойство объекта становится обязательным, и наоборот. Глобальная среда имеет объектный объект, чей "объект привязки" является глобальным объектом. Другой пример
with
,
Теперь, как указано в цитируемой части, только FunctionDeclaration s, GeneratorDeclaration s и VariableStatement s создают привязки в записи объектной среды глобальной среды. Т.е. только эти привязки становятся свойствами глобального объекта.
Все остальные декларации (например, const
а также let
) хранятся в записи декларативной среды глобальной среды, которая не основана на глобальном объекте.
И то и другое let
а также var
переменные, если они объявлены на верхнем уровне скрипта, доступны вне файла скрипта. Однако только var
переменные присваиваются window
объект. Посмотрите на этот фрагмент кода в качестве доказательства:
<script>
var namedWithVar = "with var";
let namedWithLet = "with let";
</script>
<script>
console.log("Accessed directly:");
console.log(namedWithVar); // prints: with var
console.log(namedWithLet); // prints: with let
console.log("");
console.log("Accessed through window:");
console.log(window.namedWithVar); // prints: with var
console.log(window.namedWithLet); // prints: undefined
</script>
msgstr "объявления let и const определяют переменные, относящиеся к LexicalEnvironment контекста выполнения."
Это означает, что вы должны иметь доступ к переменной внутри области выполнения, но не снаружи. Это расширяет область выполнения за пределы классической структуры замыкания JS только для функций или глобальной.
Определение let
переменная глобально оставляет это открытым для интерпретации, как вы видите в Firefox, она связывает глобальную переменную, а V8/iojs - нет.
Стоит отметить, что console.log(typeof x)
будет возвращаться number
в ио. На практике вы не должны определять переменные вне модулей или функций в максимально возможной степени... особенно с const
а также let
Переменные, объявленные с помощью ключевого слова let, не создают доступных свойств для глобального объекта (окно для браузера). На самом деле, Firefox исправил свое поведение: let v = 42; 'v' in window // false
Позволяет вам объявлять переменные, которые ограничены по объему блоком, оператором или выражением, в котором они используются. Это отличается от ключевого слова var, которое определяет переменную глобально или локально для всей функции независимо от области видимости блока.
На верхнем уровне программ и функций пусть, в отличие от var, не создается свойство глобального объекта. Например:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
Область действия переменной, объявленной с помощью var, является ее текущим контекстом выполнения, который является либо включающей функцией, либо, для переменных, объявленных вне какой-либо функции, глобальным. Если вы повторно объявите переменную JavaScript, она не потеряет своего значения. Например:
var x = 1;
if (x === 1) {
var x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 2
Обратите внимание: в отличие от C, C++ и Java, JavaScript не имеет области действия уровня блока, когда вы объявляете переменную с помощью var.
Как мы упоминали ранее, let позволяет объявлять переменные, ограниченные по объему блоком, оператором или выражением, в котором он используется. Например:
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// output: 2
}
console.log(x);
// output: 1
Здесь я рекомендую прочитать о Variable Scope