Cosa significa "var FOO = FOO || {} "(Assegna una variabile o un oggetto vuoto a quella variabile) significa in Javascript?


99

Guardando un codice sorgente online mi sono imbattuto in questo all'inizio di diversi file sorgente.

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

Ma non ho idea di cosa || {}faccia.

So che {}è uguale a new Object()e penso che ||sia per qualcosa del tipo "se esiste già usa il suo valore altrimenti usa il nuovo oggetto.

Perché dovrei vederlo all'inizio di un file sorgente?


Nota: la domanda è stata modificata per riflettere che si tratta di un modello di codice comunemente visualizzato nella parte superiore dei file sorgente Javascript.
Robert Harvey

Risposte:


153

La tua ipotesi sull'intento di || {}è abbastanza vicina.

Questo particolare modello, quando visto all'inizio dei file, viene utilizzato per creare uno spazio dei nomi , cioè un oggetto con nome sotto il quale è possibile creare funzioni e variabili senza inquinare indebitamente l'oggetto globale.

Il motivo per cui viene utilizzato è che se hai due (o più) file:

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

e

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

entrambi condividono lo stesso spazio dei nomi, quindi non importa in quale ordine vengono caricati i due file, si ottiene comunque func1e func2correttamente definito correttamente all'interno MY_NAMESPACEdell'oggetto.

Il primo file caricato creerà l' MY_NAMESPACEoggetto iniziale e qualsiasi file caricato successivamente amplierà l'oggetto.

Utilmente, questo consente anche il caricamento asincrono di script che condividono lo stesso spazio dei nomi che può migliorare i tempi di caricamento della pagina. Se i <script>tag hanno l' deferattributo impostato, non puoi sapere in quale ordine verranno interpretati, quindi come descritto sopra questo risolve anche quel problema.


2
Questo è esattamente il caso, ci sono un paio di file js con la stessa identica dichiarazione all'inizio, grazie mille!
Ricardo Sanchez

41
+1 per leggere tra le righe e spiegare i motivi per farlo. È sempre positivo quando qualcuno dà la risposta che l'utente desiderava effettivamente piuttosto che solo quella che aveva chiesto. :)
Spudley

1
mi piace dire che è il # ifndef / # define per javascript :)
Darren Kopp

1
||è anche molto utile quando si desidera fornire argomenti opzionali e inizializzarli ai valori predefiniti se non forniti:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
crazy2be

1
@ crazy2be che non funziona se l'impostazione predefinita è true, ma anche i valori false sono legali, dal momento che l' ||operatore non può dire undefinedda falsey.
Alnitak

23
var AEROTWIST = AEROTWIST || {};

Fondamentalmente questa riga sta dicendo imposta la AEROTWISTvariabile al valore della AEROTWISTvariabile o impostala su un oggetto vuoto.

Il double pipe ||è un'istruzione OR e la seconda parte dell'OR viene eseguita solo se la prima parte restituisce false.

Pertanto, se AEROTWISTha già un valore, verrà mantenuto come tale valore, ma se non è stato impostato prima, verrà impostato come oggetto vuoto.

è fondamentalmente lo stesso che dire questo:

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

Spero che aiuti.


1
in realtà l'ambito andrebbe bene nel tuo ultimo esempio perché JS non ha l'ambito di blocco
Alnitak,

@ Alnitak - meh, hai ragione; Ultimamente ho lavorato troppo con le chiusure e ho dimenticato le basi. Modificherò la risposta.
Spudley

6

Un altro uso comune di || è impostare un valore predefinito per un parametro di funzione non definito anche:

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

L'equivalente in un'altra programmazione di solito è:

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

Non è necessario varprima a, aentra nel contesto di esecuzione della funzione come parametro formale , quindi è già dichiarato.
Fabrício Matté

6

Ci sono due parti principali che var FOO = FOO || {};copre.

# 1 Prevenire gli override

Immagina di avere il tuo codice suddiviso su più file e anche i tuoi colleghi stanno lavorando su un oggetto chiamato FOO. Quindi potrebbe portare al caso che qualcuno abbia già definito FOOe assegnato una funzionalità (come una skateboardfunzione). Quindi lo sovrascriveresti, se non stavi controllando se esiste già.

Caso problematico:

// 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 questo caso la skateboardfunzione sparirà se carichi il file JavaScript homer.jsdopo bart.jsnel tuo HTML perché Homer definisce un nuovo FOOoggetto (e quindi sovrascrive quello esistente da Bart) quindi conosce solo la donutfunzione.

Quindi è necessario utilizzare var FOO = FOO || {};che significa "FOO verrà assegnato a FOO (se esiste già) o un nuovo oggetto vuoto (se FOO non esiste già).

Soluzione:

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

Poiché Bart e Homer ora stanno verificando l'esistenza di FOOprima di definire i loro metodi, puoi caricare bart.jse homer.jsin qualsiasi ordine senza sovrascrivere i metodi dell'altro (se hanno nomi diversi). Quindi otterrai sempre un FOOoggetto che ha i metodi skateboarde donut(Yay!).

# 2 Definizione di un nuovo oggetto

Se hai letto il primo esempio, hai già capito qual è lo scopo del file || {}.

Perché se non c'è un FOOoggetto esistente , il caso OR diventerà attivo e creerà un nuovo oggetto, così potrai assegnargli delle funzioni. Piace:

var FOO = {};

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

3

Se non è presente alcun valore in AEROTWIST o è nullo o non definito il valore assegnato al nuovo AEROTWIST sarà {} (un oggetto vuoto)


1

L' ||operatore assume due valori:

a || b

Se è vero , tornerà a. Altrimenti, tornerà b.

I valori sono falsy null, undefined, 0, "", NaNe false. I valori sinceri sono tutto il resto.

Quindi se anon è stato impostato (è così undefined) tornerà b.


Non sono sicuro che il vero e il falso dovrebbero essere perpetuati come parole reali. Divertente, ma non esattamente standard. :-)
Orbling

4
@Orbling sono abbastanza comunemente usati per parlare di tali valori in JS.
Alnitak

+1 per descrivere correttamente l'operatore, poiché non è un operatore logico. A volte si chiama "operatore predefinito".
Tim Büthe

@Tim L'unica differenza tra ||in JS (e Perl) e la versione in C, C ++ e Java è che JS non esegue il cast del risultato in un booleano. È ancora un operatore logico.
Alnitak

@ Alnitak: forse a causa del background non professionale degli sviluppatori JS in passato.
Orbling

-1

Si noti che in alcune versioni di IE questo codice non funzionerà come previsto. Perché la var, la variabile è ridefinita e assegnata così - se ricordo bene il problema - finirai per avere sempre un oggetto nuovo. Questo dovrebbe risolvere il problema:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.