Нет, нет никакой пользы от ОЗУ или чего-то в этом роде.
То, о чем говорит w3schools, я называю Ужас неявных глобалов . Рассмотрим эту функцию:
function foo() {
var variable1, variable2;
variable1 = 5;
varaible2 = 6;
return variable1 + variable2;
}
Кажется достаточно простым, но возвращает NaN
, а не 11
, из-за опечатки в строке varaible2 = 6;
. И он создает глобальную переменную с именем typo'd:
function foo() {
var variable1, variable2;
variable1 = 5;
varaible2 = 6;
return variable1 + variable2;
}
console.log(foo()); // NaN
console.log(varaible2); // 6?!?!?!
Это потому, что функция присваивается varaible2
(обратите внимание на опечатку), но varaible2
нигде не объявлено. Благодаря механике цепочки областей видимости в JavaScript это приводит к неявному присваиванию (новому) свойству глобального объекта (к которому вы можете обращаться как window
в браузерах).
Это просто «особенность» JavaScript в свободном режиме, назначение совершенно необъявленного идентификатора не является ошибкой; вместо этого он создает свойства для глобального объекта, а свойства глобального объекта являются глобальными переменными. (До ES5 все глобальные переменные были свойствами глобального объекта. Начиная с ES2015, был добавлен новый тип глобальных объектов, который не является свойством глобального объекта. Global-scope let
, const
, и class
создать новый глобальный тип.)
Мой пример - опечатка, но, конечно, вы можете сделать это нарочно, если хотите. В конце концов, это четко определенная часть языка. Итак:
myNewGlobal = 42;
... везде, где myNewGlobal
не объявлено, будет создан новый глобал.
Но я бы настоятельно рекомендовал никогда не делать это по назначению: это затрудняет чтение и поддержку кода, и этот код будет несовместим с модулями JavaScript, когда они станут более распространенными и широко распространенными. Если вам действительно необходимо создать глобальную переменную изнутри функции во время выполнения (это уже красный флаг, но для этого есть веские причины), сделайте это явно, присваивая свойству значение window
(или любое другое, относящееся к глобальному объекту). в вашей среде: window
в браузерах):
window.myNewGlobal = 42;
На самом деле, я бы предложил использовать строгий режим ES5 . Строгий режим делает присвоение необъявленного идентификатора ошибкой, а не молча создает глобальное. Если бы мы использовали строгий режим, проблему с foo
выше было бы намного проще диагностировать:
"use strict"; // Turns on strict mode for this compilation unit
function foo() {
var variable1, variable2;
variable1 = 5;
varaible2 = 6; // <=== ReferenceError
return variable1 + variable2;
}
console.log(foo());
Несколько касательно, но в целом я бы рекомендовал по возможности избегать глобальных переменных Глобальное пространство имен уже очень, очень загромождено в браузерах. Браузер создает глобальные значения для каждого элемента в DOM с id
, для большинства элементов с name
и имеет несколько собственных предопределенных глобальных переменных (например, title
), которые могут легко конфликтовать с вашим кодом.
Вместо этого просто определите себе хорошую функцию определения объема и вставьте в нее свои символы:
(function() {
var your, symbols, here, if_they_need, to_be_shared, amongst_functions;
function doSomething() {
}
function doSomethingElse() {
}
})();
И если вы сделаете это, вы можете включить строгий режим:
(function() {
"use strict";
var your, symbols, here, if_they_need, to_be_shared, amongst_functions;
function doSomething() {
}
function doSomethingElse() {
}
})();
... который, как уже упоминалось, имеет преимущество, превращая назначения для необъявленных идентификаторов в ошибки (наряду с различными другими полезными вещами ).
Обратите внимание, что в модуле JvaScript (добавлен в ES2015, но только сейчас начинает выходить в дикую природу) строгий режим включен по умолчанию. (Это также относится к определениям class
, также новым в ES2015.)