Есть ли разница между объявлением переменной:
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;
Это создает глобальную переменную, которая также является свойством глобального объекта , к которому мы получаем доступ как windowв браузерах (или через thisглобальную область видимости в нестрогом коде). В отличие от некоторых других свойств, свойство не может быть удалено с помощью delete.
В терминах спецификации он создает привязку идентификатора для объекта Environment Record для глобальной среды . Это делает его свойством глобального объекта, поскольку в глобальном объекте хранятся привязки идентификаторов для объекта среды. Запись среды. Вот почему свойство не удаляется: это не просто свойство, это привязка идентификатора.
Привязка (переменная) определяется до запуска первой строки кода (см. «Когда это varпроисходит» ниже).
Обратите внимание, что в IE8 и более ранних версиях свойство on windowне перечисляется (не отображается в for..inвыражениях). В IE9, Chrome, Firefox и Opera его можно перечислить.
# 1,1 let a = 0;
Это создает глобальную переменную, которая не является свойством глобального объекта. Это новая вещь с ES2015.
В терминах спецификации он создает привязку идентификатора в декларативной записи среды для глобальной среды, а не для объекта записи среды. Глобальная среда уникальна в том , раскол по окружающей среде записи, один для всех старых вещей , которая идет на глобальный объект ( объект Environment Record) и другой для всех новых вещей ( let, constи функции , созданные class) , которые не делают перейти на глобальный объект.
Привязка создается до того, как будет выполнен любой пошаговый код в его включающем блоке (в данном случае, до запуска любого глобального кода), но он никоим образом не будет доступен , пока пошаговое выполнение не достигнет letоператора. Как только выполнение достигает letоператора, переменная становится доступной. (См. «Когда letи constпроизойдет» ниже.)
# 1,2 const a = 0;
Создает глобальную константу, которая не является свойством глобального объекта.
constточно так же, letза исключением того, что вы должны предоставить инициализатор ( = valueдеталь), и вы не можете изменить значение константы после ее создания. Под крышками это точно так же, letно с привязкой к идентификатору с флагом, указывающим, что его значение нельзя изменить. Использование constделает три вещи для вас:
# 2 a = 0;
Это неявно создает свойство для глобального объекта . Поскольку это нормальное свойство, вы можете удалить его. Я бы порекомендовал не делать этого, это может быть непонятно любому, кто читает ваш код позже. Если вы используете строгий режим ES5, выполнение этого (присвоение несуществующей переменной) является ошибкой. Это одна из нескольких причин использовать строгий режим.
И что интересно, опять же в IE8 и более ранних версиях свойство создано не перечисляемым (не отображается в for..inвыражениях). Это странно, особенно учитывая № 3 ниже.
# 3 window.a = 0;
Это явно создает свойство для глобального объекта, используя глобальный объект, windowкоторый ссылается на глобальный объект (в браузерах; некоторые среды без браузера имеют эквивалентную глобальную переменную, например, в globalNodeJS). Поскольку это нормальное свойство, вы можете удалить его.
Это свойство является перечислимо, на 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"
Живой пример:
Как видите, символ fooопределяется перед первой строкой, а символ bar- нет. Где это var foo = "f";утверждение, на самом деле есть две вещи: определение символа, которое происходит до запуска первой строки кода; и выполнение присвоения этому символу, что происходит, когда строка находится в пошаговом потоке. Это называется « varподъемом», поскольку var fooдеталь перемещается («поднимается») в верхнюю часть области, но foo = "f"деталь остается в своем первоначальном положении. (См. Плохо неправильно понятvar в моем анемичном небольшом блоге.)
letи constпроизойдетletи constотличаются от varнескольких способов. Способ, который имеет отношение к этому вопросу, заключается в том, что хотя определяемая ими привязка создается до запуска любого пошагового кода, она не доступна, пока не будет достигнут оператор letили const.
Итак, пока это работает:
display(a); // undefined
var a = 0;
display(a); // 0
Это выдает ошибку:
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
Остальные два способа , которыми letи constотличаются от var, которые не являются на самом деле отношение к вопросу, являются:
varвсегда применяется ко всему контексту выполнения (по всему глобальному коду или по всему коду функции в функции, где он появляется), но letи constприменяется только внутри блока, в котором они появляются. То есть varимеет функцию (или глобальную) область видимости, но letи constимеет область видимости блока.
Повторение var aв том же контексте безвредно, но если у вас есть let a(или const a), наличие другого let aили a const aили a var aявляется синтаксической ошибкой.
Вот пример, демонстрирующий это letи constвступающий в силу немедленно в их блоке до запуска любого кода в этом блоке, но недоступный до оператора letor const:
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
Обратите внимание, что второй console.logсбой, вместо доступа к aизвне блока.
window)windowОбъект получает очень, очень завален свойствами. По возможности, настоятельно рекомендуем не добавлять в беспорядок. Вместо этого оберните ваши символы в небольшой пакет и экспортируйте не более одного символа в windowобъект. (Я часто не экспортирую никакие символы в windowобъект.) Вы можете использовать функцию для хранения всего вашего кода, чтобы содержать ваши символы, и эта функция может быть анонимной, если вам нравится:
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
В этом примере мы определяем функцию и выполняем ее сразу ( ()в конце).
Функция, используемая таким образом, часто называется областью видимости . Функции, определенные в функции определения объема, могут получать доступ к переменным, определенным в функции определения объема, потому что они являются замыканиями для этих данных (см. Закрытия не сложны в моем анемичном небольшом блоге).
window['a']=0сделать, чтобы было ясно, что я использую окно как карту? это windowособый таким образом, что некоторые браузеры не позволяют это и заставить меня использовать window.a?
window.a = 0;работает только в браузерных средах и только по соглашению. Связывание глобального объекта в переменную с именем windowне в ES Spec и поэтому не будет работать, например, V8 или Node.js, в то время как this.a = 0;(при вызове в глобальном контексте выполнения) , будет работать в любой среде , поскольку спецификации действительно указать что должно быть глобальный объект. Если вы переносите код в IIFE, как в разделе « Не по теме », вы можете передать его в качестве параметра с именем или получить прямую ссылку на глобальный объект. thiswindowglobal
var a = 0;автоматически, становится свойством глобального объекта. Если я объявлю var b = 0;в объявлении функции, будет ли это также свойство какого-то базового объекта?
Сохраняя это простым:
a = 0
Код выше дает глобальную переменную области видимости
var a = 0;
Этот код даст переменную, которая будет использоваться в текущей области видимости и под ней
window.a = 0;
Обычно это то же самое, что глобальная переменная.
a под текущая сфера Ты можешь. Кроме того, ваше использование «глобальной переменной» немного не подходит - два места, где вы говорите «глобальная переменная», не более глобально, чем место, где вы этого не говорите.
<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'
window.*декларации. Это объявление выглядит наиболее безопасным от копирования вашего кода, а также ясно.
Основано на превосходном ответе TJ Crowder : ( Не по теме: избегать беспорядка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);
Вот плнкр . Надеюсь, это поможет!
В глобальном масштабе нет семантической разницы.
Но вы действительно должны избегать a=0 поскольку вы устанавливаете значение в необъявленную переменную.
Также используйте замыкания, чтобы вообще не редактировать глобальную область видимости.
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Всегда используйте затворы и всегда поднимайте их в глобальную область, когда это абсолютно необходимо. В любом случае вы должны использовать асинхронную обработку событий для большей части вашего общения.
Как упомянул @AvianMoncellor, есть ошибка IE с var a = foo объявляется только глобальная область видимости файла. Это проблема пресловутого сломанного интерпретатора IE. Эта ошибка звучит знакомо, так что, вероятно, это правда.
Так что придерживайтесь window.globalName = someLocalpointer
deletevar
var. Это просто совершенно разные механизмы, которые имеют практически одинаковый практический результат. :-)
varпрыгает до упора.