Есть ли разница между объявлением переменной:
var a=0; //1
... следующим образом:
a=0; //2
... или:
window.a=0; //3
в глобальной области?
Есть ли разница между объявлением переменной:
var a=0; //1
... следующим образом:
a=0; //2
... или:
window.a=0; //3
в глобальной области?
Да, есть несколько отличий, хотя на практике они обычно не большие.
Там четвертый способ, а 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
делает три вещи для вас:
# 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);
}
Сохранение простоты:
a = 0
В приведенном выше коде содержится глобальная переменная области видимости
var a = 0;
Этот код даст переменную, которая будет использоваться в текущей области, и под ней
window.a = 0;
Это вообще то же самое, что и глобальная переменная.
<title>Index.html</title>
<script>
var varDeclaration = true;
noVarDeclaration = true;
window.hungOnWindow = true;
document.hungOnDocument = true;
</script>
<script src="external.js"></script>
/* external.js */
console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8
console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
Существует ли глобальный объект, по которому все вары отключены по умолчанию? например: 'globals.noVar declaration'
Опираясь на отличный ответ T.J. Crowder: (Off-topic: избегайте загромождения window
)
Это пример его идеи:
Html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
</script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello !</h1>
</body>
</html>
init.js (на основе этого ответа)
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function(i) {
return _args[i];
}
};
}());
script.js
// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);
alert(a);
Здесь plnkr. Надеюсь, что это поможет!
В глобальном масштабе не существует семантической разницы.
Но вам действительно следует избегать a=0
, так как вы устанавливаете значение необъявленной переменной.
Также используйте блокировки, чтобы вообще не редактировать глобальную область
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Всегда используйте блокировки и всегда поднимайте их в глобальную область, когда это абсолютно необходимо. Вы должны использовать асинхронную обработку событий для большей части вашего общения.
Как заметил @AvianMoncellor, есть ошибка IE с var a = foo
, объявляющая глобальную область для файла. Это проблема с IE пресловутым сломанным интерпретатором. Эта ошибка звучит знакомо, поэтому, вероятно, это правда.
Итак, придерживайтесь window.globalName = someLocalpointer