Переопределение глобальной переменной Javascript?

У меня есть вопросы относительно области видимости переменных в Javascript. У меня есть серия скриптов на веб-страницах, загружаемых в разное время. Мне нужен глобальный объект с именем MyVar, например, чтобы он был доступен для всех. Я хочу избежать его переопределения, но я предполагаю, что в какой-то момент он должен быть определен первым скриптом. Мой вопрос: использует ли var MyVar = MyVar || {} решение?

Спасибо

 /**
 * Script 1
 */


var MyVar = MyVar || {};
MyVar.config = {
    x : 2,
    y : 3
};


/**
* Script 2
*/

//is this correct?
var MyVar = MyVar || {};
//to which MyVar am I assigning the apple property?
MyVar.apple = 'red';

ОБНОВЛЕНИЕ

Отличные ответы, ребята, спасибо.

И, наконец, что делает второй оператор var, когда я повторяю var MyVar = MyVar || {}; во второй раз? Создает ли он новую переменную в глобальной области видимости с именем MyVar, которой присваивается значение существующей переменной MyVar?

Другие авторы правы, предполагая, что у меня эти скрипты загружаются синхронно в тегах <script>, однако из-за разделения труда я создаю скрипты, а не контролирую, когда и как они загружаются, поэтому нужен надежный метод для создания/использования моего объекта MyVar .

Спасибо


person JackMahoney    schedule 10.01.2013    source источник
comment
comment
Да, ваш код будет работать. Да, вы должны избегать глобальных переменных, когда это возможно.   -  person wless1    schedule 11.01.2013
comment
Прочитайте var MyVar = MyVar || {}; как var MyVar = MyVar if it exists (and isn't equal to false or 0) , or a new object if it doesn't.   -  person ic3b3rg    schedule 11.01.2013


Ответы (4)


У меня есть серия скриптов на веб-страницах, загружаемых в разное время.

Загружается ли какой-либо из них асинхронно? Если это просто набор тегов <script>, они будут загружены синхронно, последовательно.

какой MyVar я назначаю свойство яблока?

Если вы каждый раз объявляете MyVar в глобальной области видимости, будет только один MyVar. Свойство apple будет создано в существующей переменной, если она существует, или в пустом объекте, созданном с помощью var MyVar = MyVar || {};, если его нет.

Итог: после первого var MyVar = MyVar || {}; последующие объявления будут игнорироваться, а новые свойства будут добавлены к существующей переменной. Просто будьте осторожны, чтобы не перезаписать существующие свойства.

person bfavaretto    schedule 11.01.2013
comment
Это хорошее объяснение. И последнее: что делает второй оператор var, когда я повторяю var MyVar = MyVar || {}; во второй раз? Создает ли он новую переменную в глобальной области видимости с именем MyVar, которой присваивается значение существующей переменной MyVar? - person JackMahoney; 11.01.2013
comment
Он будет делать MyVar = MyVar (что, по сути, вообще ничего не делает). - person bfavaretto; 11.01.2013
comment
@JackMahoney. Чтобы уточнить, только первое определение var для конкретного имени переменной фактически определяет эту переменную. Любой последующий оператор var для того же имени переменной по существу ничего не делает; в частности, он не создает новую переменную с тем же именем. - person David R Tribble; 10.11.2016

Ваш код правильный и, вероятно, будет работать так, как ожидалось, но имейте в виду область, в которой создается MyVar. Предполагая, что ваши файлы опубликованы, они создадут MyVar в области window (при условии контекста браузера). Если один из них был завернут в анонимную функцию, как это часто бывает с Шаблон модуля, MyVar будет создан только в рамках этой функции:

(function() {
    var MyVar = MyVar || {};
    // If MyVar doesn't already exist in the global context,
    // the current MyVar reference will only be scoped to this function.
})();

Лучше использовать следующий шаблон:

var MyVar = window.MyVar || (window.MyVar = {});

Это гарантирует, что он всегда будет создаваться и ссылаться на него из глобальной области. Вы даже можете передать контекст, чтобы упростить будущие рефакторинги:

(function(context) {
    var MyVar = context.MyVar || (context.MyVar = {}));
})(window);
person roryf    schedule 10.01.2013
comment
Спасибо. Итак, в var MyVar = window.MyVar является ли MyVar ссылкой на window.MyVar или это присвоение значения? - person JackMahoney; 11.01.2013
comment
Если window.MyVar существует, ваша локальная переменная MyVar будет ссылкой на нее. Если он не существует, вторая часть || (window.MyVar = {}) создаст новый объект, назначит его window.MyVar и вернет ссылку, которая будет присвоена локальной переменной MyVar. - person roryf; 11.01.2013

Это легко проверить:

var MyVar = MyVar || {};
MyVar.config = {
    x : 2,
    y : 3
};

console.log(MyVar);

var MyVar = MyVar || {};
MyVar.apple = 'red';

console.log(MyVar);
person ic3b3rg    schedule 10.01.2013
comment
Что делать, если порядок ссылок на сценарии изменен? Ваш пример не является хорошим защитным программированием. - person roryf; 11.01.2013
comment
Я прочитал это как два отдельных сценария уровня окна. Я предполагаю, что их можно переупорядочить в html, но я думаю, что это выходит за рамки вопроса Джека. - person ic3b3rg; 11.01.2013
comment
@ ic3b3rg, вы правы, это два отдельных скрипта, и я не знаю, в каком порядке они будут - person JackMahoney; 11.01.2013
comment
В этом случае совет @roryf лучше, хотя вы можете найти мое предложение протестировать с помощью console.log полезным. - person ic3b3rg; 11.01.2013

Вот как я это делаю:

window.myVar||(window.myVar={});

Таким образом, вы не объявляете переменную повторно, если она уже существует.

person Christophe    schedule 11.01.2013