Что означает "var FOO = FOO || {}" (назначить переменную или пустой объект этой переменной) в Javascript?

Глядя на исходный код в Интернете, я наткнулся на это в верхней части нескольких исходных файлов.

var FOO = FOO || {};
FOO.Bar = …;

Но я понятия не имею, что || {} делает.

я знаю {} равно new Object() и я думаю, что || для чего-то вроде "если он уже существует, используйте его значение, иначе используйте новый объект.

Почему я вижу это в верхней части исходного файла?

8 ответов

Решение

Ваше предположение о намерении || {} довольно близко

Этот конкретный шаблон, когда он виден вверху файлов, используется для создания пространства имен, то есть именованного объекта, в котором функции и переменные могут создаваться без чрезмерного загрязнения глобального объекта.

Причина, по которой он используется, заключается в том, что если у вас есть два (или более) файла:

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}

а также

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}

оба из которых имеют одинаковое пространство имен, тогда не имеет значения, в каком порядке загружены два файла, вы все равно получаете func1 а также func2 правильно определены в MY_NAMESPACE объект правильно.

Первый загруженный файл создаст начальный MY_NAMESPACE объект, и любой впоследствии загруженный файл будет дополнять объект.

Полезно, что это также позволяет асинхронную загрузку сценариев, которые используют одно и то же пространство имен, что может улучшить время загрузки страницы. Если <script> теги имеют defer набор атрибутов, вы не можете знать, в каком порядке они будут интерпретироваться, поэтому, как описано выше, это также решает эту проблему.

var AEROTWIST = AEROTWIST || {};

В основном эта строка говорит установить AEROTWIST переменная к значению AEROTWIST переменная, или установите его для пустого объекта.

Двойная труба || является оператором OR, а вторая часть OR выполняется только в том случае, если первая часть возвращает false.

Следовательно, если AEROTWIST уже имеет значение, оно будет сохранено как это значение, но если оно не было установлено ранее, то оно будет установлено как пустой объект.

это в основном то же самое, что сказать это:

if(!AEROTWIST) {var AEROTWIST={};}

Надеюсь, это поможет.

Есть две основные части, которые var FOO = FOO || {}; охватывает.

# 1 Предотвращение переопределений

Представьте, что ваш код разделен на несколько файлов, и ваши коллеги также работают над объектом под названием FOO, Тогда это может привести к тому, что кто-то уже определил FOO и назначил ему функциональность (например, skateboard функция). Тогда вы переопределите его, если не проверяете, существует ли он уже.

Проблемный случай:

// Definition of co-worker "Bart" in "bart.js"
var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker "Homer" in "homer.js"
var FOO = {};

FOO.donut = function() {
  alert('I like donuts!');
};

В этом случае skateboard функция исчезнет, ​​если вы загрузите файл JavaScript homer.js после bart.js в вашем HTML, потому что Гомер определяет новый FOO объект (и, следовательно, переопределяет существующий от Барта), поэтому он знает только о donut функция.

Так что вам нужно использовать var FOO = FOO || {}; что означает "FOO будет назначен FOO (если он уже существует) или новому пустому объекту (если FOO еще не существует).

Решение:

var FOO = FOO || {};

// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker Homer in homer.js
var FOO = FOO || {};

FOO.donut = function() {
  alert('I like donuts!');
};

Потому что Барт и Гомер сейчас проверяют существование FOO прежде чем они определят свои методы, вы можете загрузить bart.js а также homer.js в любом порядке без переопределения методов друг друга (если они имеют разные имена). Так что вы всегда получите FOO объект, который имеет методы skateboard а также donut (Ура!).

# 2 Определение нового объекта

Если вы прочитали первый пример, то уже сейчас знаете, какова цель || {},

Потому что, если не существует FOO объект, тогда OR-case станет активным и создаст новый объект, так что вы можете назначить ему функции. Подобно:

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

Другое общее использование для || также установить значение по умолчанию для неопределенного параметра функции:

function display(a) {
  a = a || 'default'; // here we set the default value of a to be 'default'
  console.log(a);
}

// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console

Эквивалент в другом программировании обычно:

function display(a = 'default') {
  // ...
}

Если в AEROTWIST нет значения или оно равно нулю или не определено, значение, назначенное новому AEROTWIST, будет {} (пустой объект)

|| Оператор принимает два значения:

a || b

Если это правда, он вернется a, В противном случае он вернется b,

Ложные значения null, undefined, 0, "", NaN а также false, Истинные ценности - это все остальное.

Так что если a не было установлено (это undefined) он вернется b,

Для || операций, JS вернет ПЕРВОЕ "истинное" значение, которое он найдет (чтение слева направо):

      var bob = false || undefined ||  0  ||  null || "hi"
//          ^          ^         ^      ^        ^
//          nope       nope      nope   nope     yip
//
// => bob = "hi"

// --------------
// breaking
// --------------
var bob = false || "hi" ||  0  ||  null || undefined
//          ^       ^
//          nope    yip <-- stops here
//                          the rest are ignored
//
// => bob = "hi"

Еще одна хитрость - использовать && (и), чтобы убедиться, что что-то существует, прежде чем обращаться к нему.

Для операций && JS вернет ПОСЛЕДНЕЕ «правдивое» значение, которое он найдет (чтение слева направо).

Например, если вы пытаетесь прочитать свойство из многоуровневого объекта.

      var obj = {
        foo : {
            bar : "hi"
        }
    }

var bob = obj && obj.foo && obj.foo.bar;
//          ^        ^              ^
//          yip      yip            use this
//
// => bob = "hi"

// --------------
// breaking:
// --------------
var bob = obj && obj.foo && obj.foo.sally && obj.foo.bar;
//        ^          ^              ^
//        yip        yip            nope  <-- stops here, 
//                   ^                        and returns the last "yip"
//                   |                        the rest are ignored   |
//                   '-----------------------------------------------'
//
// => bob = obj.foo

Оба || и операции && читаются слева направо ... поэтому у вас могут быть вещи, которые обычно могут вызывать ошибки в направлении правой стороны, поскольку JS просто перестанет читать слева направо, как только обнаружит истинное / ложное значение.

Обратите внимание, что в некоторых версиях IE этот код не будет работать должным образом. Поскольку varпеременная переопределяется и присваивается, поэтому - если я правильно помню проблему - у вас всегда будет новый объект. Это должно решить проблему:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
Другие вопросы по тегам