Was bedeutet „var FOO = FOO || {} ”(Dieser Variablen eine Variable oder ein leeres Objekt zuweisen) bedeutet in Javascript?

99

Beim Betrachten eines Online-Quellcodes bin ich oben in mehreren Quelldateien darauf gestoßen.

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

Aber ich habe keine Ahnung was || {}macht.

Ich weiß, {}ist gleich new Object()und ich denke, das ||ist für so etwas wie "Wenn es bereits existiert, benutze seinen Wert, sonst benutze das neue Objekt.

Warum sollte ich das oben in einer Quelldatei sehen?

Ricardo Sanchez
quelle
Hinweis: Die Frage wurde bearbeitet, um zu berücksichtigen, dass dies ein Codemuster ist, das häufig oben in Javascript-Quelldateien angezeigt wird.
Robert Harvey

Antworten:

153

Ihre Vermutung bezüglich der Absicht von || {}ist ziemlich nah.

Dieses spezielle Muster wird oben in Dateien verwendet, um einen Namespace zu erstellen , dh ein benanntes Objekt, unter dem Funktionen und Variablen erstellt werden können, ohne das globale Objekt übermäßig zu verschmutzen.

Der Grund, warum es verwendet wird, ist, dass wenn Sie zwei (oder mehr) Dateien haben:

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

und

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

Beide haben denselben Namespace, es spielt dann keine Rolle, in welcher Reihenfolge die beiden Dateien geladen werden. Sie erhalten func1und func2werden dennoch korrekt im MY_NAMESPACEObjekt definiert .

Die erste geladene Datei erstellt das ursprüngliche MY_NAMESPACEObjekt, und jede anschließend geladene Datei erweitert das Objekt.

Dies ermöglicht auch das asynchrone Laden von Skripten mit demselben Namespace, wodurch die Ladezeiten für Seiten verbessert werden können. Wenn für die <script>Tags das deferAttribut festgelegt ist, können Sie nicht wissen, in welcher Reihenfolge sie interpretiert werden. Wie oben beschrieben, wird das Problem dadurch ebenfalls behoben.

Alnitak
quelle
2
Dies ist genau der Fall, es gibt ein paar js-Dateien mit genau der gleichen Deklaration am Anfang, vielen Dank!
Ricardo Sanchez
41
+1 für das Lesen zwischen den Zeilen und das Erklären der Gründe dafür. Es ist immer gut, wenn jemand die Antwort gibt, die der Benutzer tatsächlich wollte, und nicht nur die, nach der er gefragt hat. :)
Spudley
1
Ich möchte sagen, es ist das # ifndef / # define für Javascript :)
Darren Kopp
1
||ist auch sehr nützlich, wenn Sie optionale Argumente bereitstellen und diese auf function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
Standardwerte
1
@ crazy2be das funktioniert nicht, wenn die Standardeinstellung wahr ist, aber Falsey-Werte sind auch legal, da der ||Operator nicht undefineddavon unterscheiden kann falsey.
Alnitak
23
var AEROTWIST = AEROTWIST || {};

Grundsätzlich heißt es in dieser Zeile, die AEROTWISTVariable auf den Wert der AEROTWISTVariablen oder auf ein leeres Objekt zu setzen.

Die Doppelpipe ||ist eine OR-Anweisung, und der zweite Teil des OR wird nur ausgeführt, wenn der erste Teil false zurückgibt.

Wenn also AEROTWISTbereits ein Wert vorhanden ist, wird dieser Wert beibehalten. Wenn er jedoch noch nicht festgelegt wurde, wird er als leeres Objekt festgelegt.

Es ist im Grunde dasselbe wie das zu sagen:

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

Hoffentlich hilft das.

Spudley
quelle
1
Tatsächlich wäre der Bereich in Ihrem letzten Beispiel in Ordnung, da JS keinen Blockbereich hat
Alnitak
@Alnitak - meh, du hast recht; Ich habe in letzter Zeit zu viel mit Verschlüssen gearbeitet und die Grundlagen vergessen. Ich werde die Antwort bearbeiten.
Spudley
6

Eine weitere häufige Verwendung für || ist, einen Standardwert für einen undefinierten Funktionsparameter festzulegen:

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

Das Äquivalent in anderen Programmen ist normalerweise:

function display(a = 'default') {
  // ...
}
Alessioalex
quelle
Sie müssen nicht varvor a, agibt den Ausführungskontext der Funktion als formalen Parameter ein , daher ist er bereits deklariert.
Fabrício Matté
6

Es gibt zwei Hauptteile, die var FOO = FOO || {};abdecken.

# 1 Überschreibungen verhindern

Stellen Sie sich vor, Sie haben Ihren Code auf mehrere Dateien aufgeteilt und Ihre Mitarbeiter arbeiten auch an einem Objekt namens FOO. Dann könnte es zu dem Fall kommen, dass jemand bereits FOOFunktionen definiert und zugewiesen hat (wie eine skateboardFunktion). Dann würden Sie es überschreiben, wenn Sie nicht prüfen würden, ob es bereits existiert.

Problematischer Fall:

// 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!');
};

In diesem Fall wird die skateboardwird Funktion weg , wenn Sie die JavaScript - Datei laden , homer.jsnachdem bart.jsin Ihrem HTML , weil Homer ein neues definiert FOOObjekt (und damit überschreibt die bestehenden von Bart) , so dass es nur über die weiß - donutFunktion.

Sie müssen var FOO = FOO || {};also Folgendes verwenden : "FOO wird FOO zugewiesen (sofern es bereits vorhanden ist) oder einem neuen leeren Objekt (falls FOO noch nicht vorhanden ist).

Lösung:

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!');
};

Da Bart und Homer sind nun für die Existenz der Überprüfung , FOObevor sie ihre Methoden definieren, können Sie laden bart.jsund homer.jsin beliebiger Reihenfolge ohne zwingende jeweils andere Methoden (wenn sie unterschiedliche Namen haben). Sie erhalten also immer ein FOOObjekt mit den Methoden skateboardund donut(Yay!).

# 2 Ein neues Objekt definieren

Wenn Sie das erste Beispiel durchgelesen haben, dann wissen Sie schon jetzt, wozu das dient || {}.

Wenn kein FOOObjekt vorhanden ist, wird der ODER-Fall aktiv und erstellt ein neues Objekt, sodass Sie ihm Funktionen zuweisen können. Mögen:

var FOO = {};

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

Wenn AEROTWIST keinen Wert enthält oder null oder undefiniert ist, lautet der dem neuen AEROTWIST zugewiesene Wert {} (ein leeres Objekt).

Sudipto
quelle
1

Der ||Operator nimmt zwei Werte an:

a || b

Wenn a wahr ist , wird es zurückkehren a. Andernfalls wird es zurückgegeben b.

Die falsy Werte sind null, undefined, 0, "", NaNund false. Die wahrheitsgemäßen Werte sind alles andere.

Wenn aes nicht eingestellt wurde (ist es undefined), wird es zurückkehren b.

pimvdb
quelle
Ich bin mir nicht sicher, ob Wahrheit und Falschheit als tatsächliche Worte verewigt werden sollten. Amüsant, aber nicht gerade Standard. :-)
Orbling
4
@Orbling werden häufig verwendet, um über solche Werte in JS zu sprechen.
Alnitak
+1 für die korrekte Beschreibung des Operators, da es sich nicht um einen logischen Operator handelt. Manchmal wird es "Standardoperator" genannt.
Tim Büthe
@Tim Der einzige Unterschied zwischen ||JS (und Perl) und der Version in C, C ++ und Java besteht darin, dass JS das Ergebnis nicht in einen Booleschen Wert umwandelt . Es ist immer noch ein logischer Operator.
Alnitak
@Alnitak: Möglicherweise aufgrund des nicht professionellen Hintergrunds von JS-Entwicklern in der Vergangenheit.
Orbling
-1

Beachten Sie, dass dieser Code in einigen IE-Versionen nicht wie erwartet funktioniert. Da die varVariable neu definiert und zugewiesen wird, haben Sie - wenn ich mich richtig an das Problem erinnere - immer ein neues Objekt. Das sollte das Problem beheben:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
ZER0
quelle