Que signifie “var FOO = FOO || {} ”(Attribuer une variable ou un objet vide à cette variable) signifie en Javascript?

99

En regardant un code source en ligne, je suis tombé sur cela en haut de plusieurs fichiers source.

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

Mais je n'ai aucune idée de ce que || {}ça fait.

Je sais que {}c'est égal à new Object()et je pense que le ||est pour quelque chose comme "s'il existe déjà, utilisez sa valeur, sinon utilisez le nouvel objet.

Pourquoi verrais-je cela en haut d'un fichier source?

Ricardo Sanchez
la source
Remarque: la question a été modifiée pour indiquer qu'il s'agit d'un modèle de code couramment observé en haut des fichiers source Javascript.
Robert Harvey

Réponses:

153

Votre estimation de l'intention de || {}est assez proche.

Ce modèle particulier vu en haut des fichiers est utilisé pour créer un espace de noms , c'est-à-dire un objet nommé sous lequel des fonctions et des variables peuvent être créées sans polluer indûment l'objet global.

La raison pour laquelle il est utilisé est que si vous avez deux fichiers (ou plus):

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

et

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

qui partagent le même espace de noms, peu importe dans quel ordre les deux fichiers sont chargés, vous obtenez toujours func1et func2correctement défini dans l' MY_NAMESPACEobjet correctement.

Le premier fichier chargé créera l' MY_NAMESPACEobjet initial et tout fichier chargé ultérieurement augmentera l'objet.

Utilement, cela permet également le chargement asynchrone de scripts qui partagent le même espace de noms, ce qui peut améliorer les temps de chargement des pages. Si les <script>balises ont l' deferattribut défini, vous ne pouvez pas savoir dans quel ordre elles seront interprétées, donc comme décrit ci-dessus, cela résout également ce problème.

Alnitak
la source
2
C'est exactement le cas, il y a quelques fichiers js avec exactement la même déclaration au début, merci beaucoup!
Ricardo Sanchez
41
+1 pour lire entre les lignes et expliquer les raisons de le faire. C'est toujours bien quand quelqu'un donne la réponse que l'utilisateur voulait réellement plutôt que celle qu'il a demandée. :)
Spudley
1
j'aime dire que c'est le # ifndef / # define pour javascript :)
Darren Kopp
1
||est également très utile lorsque vous souhaitez fournir des arguments optionnels et les initialiser aux valeurs par défaut s'ils ne sont pas fournis:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
crazy2be
1
@ crazy2be qui ne fonctionne pas si le défaut est truthy, mais les valeurs de Falsey sont également juridique, puisque l' ||opérateur ne peut pas dire undefinedde falsey.
Alnitak le
23
var AEROTWIST = AEROTWIST || {};

Fondamentalement, cette ligne indique définir la AEROTWISTvariable sur la valeur de la AEROTWISTvariable, ou la définir sur un objet vide.

Le double tube ||est une instruction OR, et la seconde partie de OR n'est exécutée que si la première partie renvoie false.

Par conséquent, s'il a AEROTWISTdéjà une valeur, elle sera conservée comme cette valeur, mais si elle n'a pas été définie auparavant, elle sera définie comme un objet vide.

c'est fondamentalement la même chose que de dire ceci:

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

J'espère que cela pourra aider.

Spudley
la source
1
en fait, la portée serait bien dans votre dernier exemple car JS n'a pas de portée de bloc
Alnitak
@Alnitak - meh, vous avez raison; J'ai trop travaillé avec des fermetures ces derniers temps et j'ai oublié les bases. Je vais modifier la réponse.
Spudley
6

Une autre utilisation courante pour || est de définir une valeur par défaut pour un paramètre de fonction non défini également:

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'équivalent dans d'autres programmes est généralement:

function display(a = 'default') {
  // ...
}
alessioalex
la source
Vous n'avez pas besoin varde a, aentre le contexte d'exécution de la fonction en tant que paramètre formel , il est donc déjà déclaré.
Fabrício Matté
6

Il y a deux parties principales qui var FOO = FOO || {};couvrent.

# 1 Empêcher les remplacements

Imaginez que votre code soit divisé sur plusieurs fichiers et que vos collègues travaillent également sur un objet appelé FOO. Ensuite, cela pourrait conduire au cas où quelqu'un a déjà défini FOOet affecté des fonctionnalités (comme une skateboardfonction). Ensuite, vous le remplaceriez, si vous ne vérifiiez pas s'il existe déjà.

Cas problématique:

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

Dans ce cas, la skateboardfonction disparaîtra si vous chargez le fichier JavaScript homer.jsaprès bart.jsdans votre HTML car Homer définit un nouvel FOOobjet (et remplace donc celui existant de Bart) afin qu'il ne connaisse que la donutfonction.

Vous devez donc utiliser var FOO = FOO || {};ce qui signifie "FOO sera assigné à FOO (s'il existe déjà) ou à un nouvel objet vide (si FOO n'existe pas déjà).

Solution:

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

Parce que Bart et Homer vérifient maintenant l'existence de FOOavant de définir leurs méthodes, vous pouvez charger bart.jset homer.jsdans n'importe quel ordre sans remplacer les méthodes de l'autre (si elles ont des noms différents). Ainsi, vous obtiendrez toujours un FOOobjet qui a les méthodes skateboardet donut(Yay!).

# 2 Définition d'un nouvel objet

Si vous avez lu le premier exemple, alors vous savez déjà quel est le but du || {}.

Parce que s'il n'y a pas d' FOOobjet existant, le cas OR deviendra actif et créera un nouvel objet, vous pouvez donc lui attribuer des fonctions. Comme:

var FOO = {};

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

S'il n'y a pas de valeur dans AEROTWIST ou si elle est nulle ou non définie, la valeur affectée au nouvel AEROTWIST sera {} (un objet vide)

sudipto
la source
1

L' ||opérateur prend deux valeurs:

a || b

Si a est vrai , il reviendra a. Sinon, il reviendra b.

Les valeurs falsy sont null, undefined, 0, "", NaNet false. Les valeurs de vérité sont tout le reste.

Donc, si an'a pas été défini (est-ce undefined), il reviendra b.

pimvdb
la source
Je ne suis pas sûr que la vérité et le faux devraient être perpétués en tant que mots réels. Amusant, mais pas tout à fait standard. :-)
Orbling
4
@Orbling, ils sont assez couramment utilisés pour parler de telles valeurs dans JS.
Alnitak
+1 pour décrire correctement l'opérateur, car ce n'est pas un opérateur logique. Parfois, il est appelé "opérateur par défaut".
Tim Büthe
@Tim La seule différence entre ||JS (et Perl) et la version en C, C ++ et Java est que JS ne convertit pas le résultat en booléen. C'est toujours un opérateur logique.
Alnitak
@Alnitak: Peut-être en raison de l'expérience non professionnelle des développeurs JS dans le passé.
Orbling
-1

Notez que dans certaines versions d'IE, ce code ne fonctionnera pas comme prévu. Parce que le var, la variable est redéfinie et assignée donc - si je me souviens bien du problème - vous finirez par avoir toujours un nouvel objet. Cela devrait résoudre le problème:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
ZER0
la source