Comment fonctionne cette syntaxe JavaScript/JQuery: (function (window, undefined) {}) (window)?
avez-vous déjà regardé sous le capot le code source jQuery 1.4 et remarqué comment il est encapsulé de la façon suivante:
(function( window, undefined ) {
//All the JQuery code here
...
})(window);
j'ai lu un article sur L'espace de nom JavaScript et un autre appelé une paire importante de Parens ," donc je sais ce qui se passe ici.
Mais je n'ai jamais vu cette syntaxe particulière avant. Qu'est-ce que que undefined
fait là? Et pourquoi window
doit-il être passé et apparaître à nouveau à la fin?
5 réponses
la variable non définie est une variable normale et peut être changée simplement avec undefined = "new value";
. Donc jQuery crée une variable locale "non définie" qui est vraiment non définie.
la variable window est rendue locale pour des raisons de performance. Parce que quand JavaScript regarde une variable, il passe d'abord par les variables locales jusqu'à ce qu'il trouve le nom de la variable. Quand il n'est pas trouvé, JavaScript passe par la portée suivante, etc. jusqu'à ce qu'il passe à travers les variables globales. Donc, si l' la variable window est rendue locale, JavaScript peut la chercher plus rapidement. Pour plus d'informations: Accélérez votre JavaScript - Nicholas C. Zakas
Non défini
en déclarant undefined
comme argument mais en ne lui passant jamais de valeur, garantit qu'il est toujours non défini, car il s'agit simplement d'une variable dans le champ d'Application global qui peut être écrasée. Cela fait de a === undefined
une alternative sûre à typeof a == 'undefined'
, ce qui sauve quelques caractères. Il rend également le code plus convivial, car undefined
peut être raccourci à u
par exemple, en sauvegardant quelques caractères supplémentaires.
fenêtre
passer window
comme argument garde une copie dans la portée locale, qui affecte la performance: http://jsperf.com/short-scope . Tous les accès à window
devront désormais parcourir un niveau de moins dans la chaîne scope. Comme pour undefined
, une copie locale permet une minification plus agressive.
Note complémentaire:
bien que cela n'ait peut-être pas été l'intention des développeurs de jQuery, passer dans window
permet à la bibliothèque d'être plus facilement intégrée dans des environnements Javascript côté serveur, par exemple noeud.js - où il n'y a pas d'objet global window
. Dans une telle situation, une seule ligne doit être changée pour remplacer l'objet window
par un autre. Dans le cas de jQuery, un objet simulé window
peut être créé et passé dans le but de racler HTML (une bibliothèque telle que jsdom peut le faire).
D'autres ont expliqué undefined
. undefined
est comme une variable globale qui peut être redéfinie à n'importe quelle valeur. Cette technique est d'empêcher toutes les vérifications non définies de briser si quelqu'un a écrit dire, undefined = 10
quelque part. Un argument qui n'est jamais passé est garanti pour être vrai undefined
, indépendamment de la valeur de la variable undefined
.
la raison de passer la fenêtre peut être illustrée par l'exemple suivant.
(function() {
console.log(window);
...
...
...
var window = 10;
})();
Qu'est-ce que le log de la console? La valeur de l'objet window
droit? Faux! 10? 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 surprises.
Je ne sais pas si jQuery le fait, mais si vous redéfinissez window
variable locale n'importe où dans votre fonction quelle qu'en soit la raison, c'est une bonne idée de l'emprunter à global scope.
window
est passé comme ça juste au cas où quelqu'un décide de redéfinir l'objet window dans IE, je suppose la même chose pour undefined
, au cas où il est ré-assigné d'une manière ou d'une autre plus tard.
haut window
dans le script est juste de nommer l'argument de la "fenêtre", un argument de plus local que mondial window
de référence et le code à l'intérieur de cette fermeture va utiliser. Le window
à la fin spécifie en fait ce qu'il faut passer pour le premier argument, dans ce cas le sens actuel de window
...l'espoir est que vous n'avez pas foiré window
avant que cela arrive.
cela peut être plus facile à penser en montrant le cas le plus typique utilisé dans jQuery, plugin .noConflict()
manipulation, 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);
Testé avec 1000000 itérations. Ce type de localisation n'a aucun effet sur la performance. Pas même une milliseconde en 1000000 itérations. C'est tout simplement inutile.