web-dev-qa-db-fra.com

Comment fonctionne cette syntaxe JavaScript / jQuery: (fonction (fenêtre, non définie) {}) (fenêtre)?

Avez-vous déjà jeté un coup d'œil sous le capot au code source jQuery 1.4 et remarqué comment il est encapsulé de la manière suivante:

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

J'ai lu un article sur JavaScript Namespacing et un autre intitulé " An Important Pair of Parens ", donc je sais ce qui se passe ici.

Mais je n'ai jamais vu cette syntaxe particulière auparavant. Qu'est-ce que undefined y fait? Et pourquoi window doit-il être passé puis réapparaître à la fin?

152
dkinzer

L'indéfini est une variable normale et peut être modifié simplement avec undefined = "new value";. Donc jQuery crée une variable locale "non définie" qui est VRAIMENT non définie.

La variable de fenêtre est rendue locale pour des raisons de performances. Parce que lorsque JavaScript recherche une variable, il passe d'abord par les variables locales jusqu'à ce qu'il trouve le nom de la variable. Lorsqu'il n'est pas trouvé, JavaScript passe par la portée suivante, etc. jusqu'à ce qu'il filtre à travers les variables globales. Donc, si la variable de fenêtre est rendue locale, JavaScript peut la rechercher plus rapidement. Plus d'informations: Accélérez votre JavaScript - Nicholas C. Zakas

157
Vincent

Non défini

En déclarant undefined en tant qu'argument mais en ne lui passant jamais de valeur, il est toujours indéfini, car il s'agit simplement d'une variable de portée globale qui peut être remplacée. Cela fait a === undefined une alternative sûre à typeof a == 'undefined', qui enregistre quelques caractères. Cela rend également le code plus convivial pour le minifieur, car undefined peut être raccourci en u par exemple, en enregistrant quelques caractères supplémentaires.

Fenêtre

Passer window comme argument conserve une copie dans la portée locale, ce qui affecte les performances: http://jsperf.com/short-scope . Tous les accès à window devront désormais parcourir un niveau de moins dans la chaîne de portée. Comme avec undefined, une copie locale permet à nouveau une minification plus agressive.


Sidenote:

Bien que cela n'ait peut-être pas été l'intention des développeurs de jQuery, la transmission de window permet à la bibliothèque d'être plus facilement intégrée dans les environnements Javascript côté serveur, par exemple node.js - où il n'y a pas d'objet global window. Dans une telle situation, une seule ligne doit être modifiée pour remplacer l'objet window par un autre. Dans le cas de jQuery, un faux objet window peut être créé et transmis à des fins de scraping HTML (une bibliothèque telle que jsdom peut le faire).

53
David Tang

D'autres ont expliqué undefined. undefined est comme une variable globale qui peut être redéfinie en n'importe quelle valeur. Cette technique consiste à empêcher toutes les vérifications non définies de se casser si quelqu'un a écrit par exemple, undefined = 10 quelque part. Un argument qui n'est jamais passé est garanti comme étant réel undefined quelle que soit la valeur de la variableundefined.

La raison de passer la fenêtre peut être illustrée par l'exemple suivant.

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

Que consigne la console? La valeur de window objet n'est-ce pas? Faux! dix? Faux! Il enregistre undefined. L'interpréteur Javascript (ou compilateur JIT) le réécrit de cette façon -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

Cependant, si vous obtenez la variable window comme argument, il n'y a pas de var et donc pas de surprise.

Je ne sais pas si jQuery le fait, mais si vous redéfinissez la variable locale window n'importe où dans votre fonction pour une raison quelconque, c'est une bonne idée de l'emprunter à la portée globale.

16
Chetan Sastry

window est passé comme ça juste au cas où quelqu'un déciderait de redéfinir l'objet window dans IE, je suppose la même chose pour undefined, au cas où il serait réassigné d'une manière ou d'une autre plus tard.

Le haut window dans ce script ne fait que nommer l'argument "fenêtre", un argument plus local que la référence globale window et ce que le code à l'intérieur de cette fermeture utilisera. Le window à la fin spécifie réellement quoi passer pour le premier argument, dans ce cas la signification actuelle de window... l'espoir est que vous n'avez pas foiré window avant que cela n'arrive.

Cela peut être plus facile à penser en montrant le cas le plus typique utilisé dans jQuery, la gestion du plugin .noConflict() , donc pour la majorité du code, vous pouvez toujours utiliser $, même si cela signifie quelque chose autre que jQuery en dehors de cette portée:

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
6
Nick Craver

Testé avec 1000000 itérations. Ce type de localisation n'a eu aucun effet sur les performances. Pas même une seule milliseconde sur 1000000 itérations. C'est tout simplement inutile.

5
Semra