#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 /