En bref
Sommaire
Dans sa forme la plus simple, cette technique vise à envelopper le code dans une portée de fonction .
Il aide à diminuer les chances de:
- conflit avec d'autres applications / bibliothèques
- portée polluante supérieure (mondiale la plus probable)
Il ne détecte lorsque le document est prêt - il est une sorte de document.onload
niwindow.onload
Il est communément appelé Immediately Invoked Function Expression (IIFE)
ou Self Executing Anonymous Function
.
Code expliqué
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Dans l'exemple ci-dessus, toute variable définie dans la fonction (c'est-à-dire déclarée à l'aide var
) sera "privée" et accessible UNIQUEMENT dans le cadre de la fonction (comme le dit Vivin Paliath). En d'autres termes, ces variables ne sont pas visibles / accessibles en dehors de la fonction. Voir la démo en direct .
Javascript a une portée de fonction. "Les paramètres et variables définis dans une fonction ne sont pas visibles en dehors de la fonction, et qu'une variable définie n'importe où dans une fonction est visible partout dans la fonction." (extrait de "Javascript: The Good Parts").
Plus de détails
Code alternatif
En fin de compte, le code affiché avant pourrait également être fait comme suit:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Voir la démo en direct .
Les racines
Itération 1
Un jour, quelqu'un a probablement pensé "qu'il doit y avoir un moyen d'éviter de nommer" myMainFunction ", car tout ce que nous voulons, c'est l'exécuter immédiatement."
Si vous revenez à l'essentiel, vous découvrez que:
expression
: quelque chose évaluant à une valeur. c'est à dire3+11/x
statement
: ligne (s) de code faisant quelque chose MAIS il n'évalue pas une valeur. c'est à direif(){}
De même, les expressions de fonction évaluent à une valeur. Et une conséquence (je suppose?) Est qu'ils peuvent être immédiatement invoqués:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
Donc, notre exemple plus complexe devient:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Voir la démo en direct .
Itération 2
La prochaine étape est la pensée "pourquoi avoir var myMainFunction =
si nous ne l'utilisons même pas!?".
La réponse est simple: essayez de supprimer cela, comme ci-dessous:
function(){ console.log('mamamia!'); }();
Voir la démo en direct .
Cela ne fonctionnera pas car "les déclarations de fonctions ne sont pas invocables" .
L'astuce est qu'en supprimant, var myMainFunction =
nous avons transformé l' expression de fonction en une déclaration de fonction . Voir les liens dans "Ressources" pour plus de détails à ce sujet.
La question suivante est «pourquoi ne puis-je pas la conserver comme expression de fonction avec autre chose que var myMainFunction =
?
La réponse est "vous pouvez", et il y a en fait plusieurs façons de le faire: ajouter un +
, un !
, un -
, ou peut-être encapsuler une paire de parenthèses (comme c'est maintenant fait par convention), et plus je crois. Comme exemple:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
ou
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
ou
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
Donc, une fois que la modification pertinente est ajoutée à ce qui était autrefois notre "Code alternatif", nous revenons au même code exact que celui utilisé dans l'exemple "Code expliqué"
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
En savoir plus sur Expressions vs Statements
:
Démystifier les portées
Une chose que l'on pourrait se demander est "ce qui se passe lorsque vous ne définissez PAS la variable" correctement "à l'intérieur de la fonction - c'est-à-dire que vous effectuez une simple affectation à la place?"
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
Voir la démo en direct .
Fondamentalement, si une variable qui n'a pas été déclarée dans sa portée actuelle se voit attribuer une valeur, alors "une recherche dans la chaîne de portée se produit jusqu'à ce qu'elle trouve la variable ou atteigne la portée globale (à quel moment elle la créera)".
Dans un environnement de navigateur (par rapport à un environnement de serveur comme nodejs), la portée globale est définie par l' window
objet. Par conséquent, nous pouvons le faire window.myOtherFunction()
.
Mon conseil "Bonnes pratiques" sur ce sujet est de toujours l'utiliser var
lors de la définition de quelque chose : que ce soit un nombre, un objet ou une fonction, et même lorsqu'il est dans la portée globale. Cela rend le code beaucoup plus simple.
Remarque:
- javascript ne pas avoir
block scope
(Mise à jour: l' étendue de bloc variables locales ajoutées dans ES6 .)
- javascript a seulement
function scope
& global scope
( window
portée dans un environnement de navigateur)
En savoir plus sur Javascript Scopes
:
Ressources
Prochaines étapes
Une fois que vous obtenez ce IIFE
concept, il mène au module pattern
, ce qui est généralement fait en tirant parti de ce modèle IIFE. S'amuser :)