Ответ 1
Да, есть несколько отличий, хотя на практике они обычно не большие.
Там четвертый способ, а ES2015 (ES6) - еще два. Я добавил четвертый путь в конце, но вставил ES2015 после # 1 (вы увидите, почему), поэтому мы имеем:
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
Эти объяснения объясняются
# 1 var a = 0;
Это создает глобальную переменную, которая также является свойством Запись среды для глобальная среда. Это делает его объектом глобального объекта, потому что глобальный объект - это привязка идентификаторов для записи Environment Environment Environment. Вот почему свойство не является удаляемым: это не просто свойство, это привязка идентификатора.
Связывание (переменная) определяется до начала первой строки кода (см. "Когда var
происходит" ниже).
Обратите внимание, что в IE8 и ранее свойство, созданное на window
, не перечислимо (не отображается в операторах for..in
). В IE9, Chrome, Firefox и Opera это можно перечислить.
# 1.1 let a = 0;
Это создает глобальную переменную, которая не является свойством глобального объекта. Это новая вещь с ES2015.
В спецификациях он создает привязку идентификатора в декларативной записи среды для глобальной среды, а не в записи среды объекта. Глобальная среда уникальна тем, что имеет разделенную запись среды, одну для всех старых вещей, которые идут по глобальному объекту (объектная запись среды), а другая для всех новых вещей (let
, const
) и созданных функций на class
), которые не входят в глобальный объект.
Связывание создается до того, как будет выполнен любой пошаговый код в его охватывающем блоке (в этом случае, прежде чем запускается какой-либо глобальный код), но он не доступен никоим образом, пока пошаговое выполнение не достигнет let
. Как только выполнение достигнет инструкции let
, переменная доступна. (См. "Когда let
и const
произойдет" ниже.)
# 1.2 const a = 0;
Создает глобальную константу, которая не является свойством глобального объекта.
const
точно соответствует let
, за исключением того, что вы должны предоставить инициализатор (часть = value
), и вы не сможете изменить значение константы после ее создания. Под обложками это точно как let
, но с флагом в привязке идентификатора, говорящим, что его значение не может быть изменено. Использование const
делает три вещи для вас:
- Делает ошибку времени синтаксического анализа, если вы пытаетесь назначить константу.
- Документирует его неизменный характер для других программистов.
- Позволяет оптимизировать движок JavaScript на том основании, что он не изменится.
# 2 a = 0;
Это создает свойство в глобальном объекте неявно. Как нормальное свойство, вы можете удалить его. Я бы порекомендовал не делать этого, может быть неясно, кто будет читать ваш код позже.
И интересно, опять же, на IE8 и ранее, свойство, созданное не перечислимым (не отображается в операторах for..in
). Это странно, особенно учитывая № 3 ниже.
# 3 window.a = 0;
Это создает свойство в глобальном объекте явно, используя глобальный объект window
, который ссылается на глобальный объект (в браузерах, некоторые не-браузерные среды имеют эквивалентную глобальную переменную, например global
на NodeJS). Как нормальное свойство, вы можете удалить его.
Это свойство перечислимо, в IE8 и более ранних версиях, а также в каждом другом браузере, который я пробовал.
# 4 this.a = 0;
Точно как # 3, за исключением того, что мы ссылаемся на глобальный объект через this
вместо глобального window
. Однако это не будет работать в строгом режиме, потому что в строгом режиме глобального кода this
не имеет ссылки на глобальный объект (вместо этого он имеет значение undefined
).
Удаление свойств
Что я подразумеваю под "удалением" или "удалением" a
? Именно это: Удаление свойства (целиком) с помощью ключевого слова delete
:
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
delete
полностью удаляет свойство из объекта. Вы не можете сделать это с помощью свойств, добавленных в window
косвенно через var
, delete
либо молча игнорируется, либо генерирует исключение (в зависимости от реализации JavaScript и в строгом режиме).
Предупреждение: IE8 снова (и предположительно ранее, и IE9-IE11 в режиме "сломанной совместимости" ): он не позволит вам удалять свойства объекта window
, даже если вы должно быть разрешено. Хуже того, это вызывает исключение, когда вы пытаетесь (попробовать этот эксперимент в IE8 и в других браузерах). Поэтому при удалении из объекта window
вы должны быть защищены:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
Это пытается удалить свойство, и если выбрано исключение, он делает следующее лучшее и устанавливает свойство undefined
.
Этот только относится к объекту window
и только (насколько я знаю) к IE8 и ранее (или IE9-IE11 в режиме "сломанной совместимости" ). Другие браузеры прекрасно удаляют свойства window
, подчиняясь указанным выше правилам.
Когда var
происходит
Переменные, определенные с помощью оператора var
, создаются до запуска любого пошагового кода в контексте выполнения, поэтому свойство существует задолго до инструкции var
.
Это может ввести в заблуждение, поэтому давайте посмотрим:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
Живой пример:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}