Почему переменные становятся ключами в объекте window?

#javascript

#javascript

Вопрос:

Я заметил, что переменные становятся ключами, а их значения становятся значениями указанных ключей, когда я пишу в объекте window. Например:

 var variable = "value";
console.log(window.variable);//logs "value"
  

Но если я создам новый собственный объект, подобный:

 var o = {
    key: "value",
    var key2 = "value2"
}; // result: "syntax error"
  

Я должен использовать двоеточие для задания пар ключ / значение. И даже с функциями конструктора, хотя я не получаю синтаксической ошибки, я, похоже, не могу сделать это внутри функции конструктора или во время создания экземпляра объекта или после:

 function Blueprint(){
    this.key = "value";
    var key2 = "value2";
}

var o = new Blueprint;
console.log(o.key); //result: "value"
console.log(o.key2); //result: "undefined"
  

Теперь я понимаю, почему в первом случае я сгенерировал синтаксическую ошибку и почему во втором случае я не смог присоединить key2 к функции конструктора Blueprint, но чего я не понимаю, почему в глобальном объекте window мне предоставляется свобода добавлять свойства с использованием переменных, и они мгновенно становятся ключами в объекте window. Кроме объекта Windows, переменные, похоже, ведут себя так, как будто они независимы от объектов и создания свойств.

Я также заметил подобное поведение в глобальном объекте при экспериментировании с node. Являются ли глобальные объекты единственными объектами, которые могут устанавливать пары ключ / значение таким образом, используя переменные? И если да, то почему? Почему мы не вынуждены делать что-то вроде следующего при работе на глобальном уровне:

 this.key = "value";
  

Или…

 window.key = "value";
  

Это просто какое-то предостережение к поведению языка в целом или есть какая-то внутренне согласованная логика объекта window по отношению ко всем другим объектам, которая объясняет это?

Комментарии:

1. Это волшебство. Смотрите es5.github.io/#x10.2.3

2. Каждая область видимости переменной имеет объект, содержащий переменные. Так получилось, что в глобальной области видимости у нас есть прямой доступ к этому объекту.

3. …это в некотором роде похоже на arguments объект в функции. Вы передаете аргументы параметрам, и они доступны через идентификаторы параметров, но автоматически появляется этот объект, который также содержит переданные вами значения. Измените значение параметра, и оно изменится в arguments объекте, и наоборот (хотя это постоянное сопоставление не существует в строгом режиме) .

Ответ №1:

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

В браузере глобальным объектом является window .

Комментарии:

1. СЛакс, спасибо за ваш ответ, но мой вопрос был не в том, происходит ли это (совершенно очевидно, что это происходит), мой вопрос был в ТОМ, ПОЧЕМУ это происходит. Есть ли какая-то внутренняя причина для такого изменения поведения или это просто языковая оговорка. В любом случае, большое вам спасибо, я ценю ваш вклад.

2. @AllanSocks: Прочитайте спецификацию.

Ответ №2:

Глобальная среда — это так называемая объектная среда (Record):

Каждая запись окружения объекта связана с объектом, называемым объектом привязки. Запись среды объекта привязывает набор имен идентификаторов, которые непосредственно соответствуют именам свойств его объекта привязки.

Как вы можете видеть, поведение при создании свойств для идентификаторов определено явно. И в случае глобальной среды объектом привязки является глобальный объект, который находится window в браузерах.

Более подробную информацию об окружениях можно найти в спецификации:

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

Я не могу сказать вам, почему существуют эти два типа. Если вы хотите это знать, вы можете спросить по адресу http://esdiscuss.org /