qu'est-ce que c'est
Dans JavaScript, chaque fonction, lorsqu'elle est appelée, crée un nouveau contexte d'exécution. Étant donné que les variables et les fonctions définies dans les fonctions sont les seules variables accessibles en interne, et non en externe, lors de l'appel d'une fonction, le contexte fourni par la fonction fournit un moyen très simple de créer des variables privées.
fonction makeCounter () {var i = 0; return function () {console.log (++ i); }; } // Rappelez-vous: `Counter` et` `` `` COMPLEDans de nombreux cas, vous n'aurez peut-être pas besoin d'une fonction comme faire quelque chose pour renvoyer plusieurs valeurs accumulées, et vous ne pouvez l'appeler qu'une seule fois pour obtenir une seule valeur, et dans certains autres cas, vous n'avez même pas besoin de connaître explicitement la valeur de retour.
Son noyau
Maintenant, peu importe que vous définissez une fonction comme la fonction foo () {} ou var foo = function () {}, lorsque vous appelez, vous devez ajouter une paire de parenthèses après, comme foo ().
// La fonction définie ci-dessous peut être appelée en ajoutant une paire de supports après le nom de la fonction, comme `foo ()`, // parce que Foo est juste une variable de référence var foo = function () {/ * code * /} `relatif à l'expression de la fonction` fonction () {/ * Code * /} `var foo = fure () {/ * code * /} supports après? function () {/ * code * /} (); // syntaxerror: jeton inattendu (Comme vous pouvez le voir, un bug est pris ici. Lorsque les parenthèses apparaissent derrière une fonction afin d'appeler une fonction, que vous rencontriez un tel mot-clé de fonction dans l'environnement global ou l'environnement local, par défaut, il le traitera comme une déclaration de fonction plutôt que comme une expression de fonction. Si vous ne dites pas explicitement aux parenthèses qu'il s'agit d'une expression, elle la traitera comme une fonction sans nom et lancera une erreur, car la déclaration de fonction nécessite un nom.
Question 1: Puis-je penser à une question ici? Pouvons-nous également appeler la fonction var foo = function () {console.log (1)} () directement comme celle-ci, et la réponse est ok.
Question 2: De même, nous pouvons également réfléchir à une question. Si une déclaration de fonction comme celle-ci est appelée directement avec des parenthèses après, que se passe-t-il? Veuillez consulter la réponse ci-dessous.
Fonction, parenthèses, erreur
Fait intéressant, si vous spécifiez un nom pour une fonction et mettez une paire de parenthèses derrière, la même erreur sera lancée, mais cette fois, c'est pour une autre raison. Lorsque les parenthèses sont placées après une expression de fonction, cela indique qu'il s'agit d'une fonction appelée et des parenthèses sont placées après une déclaration, cela signifie qu'ils sont complètement séparés de la déclaration de fonction précédente. À l'heure actuelle, les parenthèses ne sont qu'une simple représentation d'une parenthèses (accolades utilisées pour contrôler la priorité de l'opération).
//However, the function declaration is syntactically invalid, it is still a declaration, and the following parentheses are invalid, because the parentheses need to include the expression function foo(){ /* code */ }();//SyntaxError: Unexpected token//Now, you put an expression in the parentheses without throwing an error..., but the function is not executed, because: function foo () {/ * code * /} (1) // Il est équivalent à ce qui suit, une déclaration de fonction suit une expression qui n'a aucune relation du tout: fonction foo () {/ * code * /} (1);Exécuter immédiatement les expressions de fonction (iife)
Heureusement, il est facile de corriger les erreurs de grammaire. La méthode la plus populaire et la plus acceptée consiste à envelopper les déclarations de fonction entre parenthèses pour dire à l'analyseur d'exprimer une expression de fonction, car en JavaScript, les parenthèses ne peuvent pas contenir de déclarations. Pour cette raison, lorsque les parenthèses rencontrent le mot clé de la fonction afin d'envelopper la fonction, il sait l'analyser comme une expression de fonction au lieu d'une déclaration de fonction. Faites attention à la compréhension que les parenthèses ici sont différentes des parenthèses ci-dessus lorsqu'ils rencontrent des fonctions, c'est-à-dire,
Lorsque les parenthèses apparaissent à la fin d'une fonction anonyme et souhaitent appeler une fonction, il va par défaut pour traiter la fonction comme une déclaration de fonction.
Lors de l'emballage d'une fonction entre parenthèses, il analysera la fonction comme une expression par défaut, plutôt que de déclarer la fonction.
// Les deux modèles peuvent être utilisés pour appeler immédiatement une expression de fonction, en utilisant l'exécution de la fonction pour créer des variables privées (fonction () {/ * code * /} ()); // Crockford recommande celle-ci, l'expression entre parenthèses représente immédiatement la fonction (fonction () {/ * * Code * /}) (); // mais celle-ci fonctionne tout simplement, l'expression dans les bracts représente Les opérateurs consistent à désambiguïter // entre les expressions de fonction et les déclarations de fonction, ils peuvent être // omis lorsque l'analyseur s'attend déjà à une expression (mais veuillez consulter la // "note importante" ci-dessous) .var i = function () {return 10;} (); true && function () {/ * * /} /} (); 0, function () {} (); // Si vous ne vous souciez pas de la valeur de retour, ou de la lecture en tant que lecture en tant que lecture en tant que lecture en tant que lecture en tant que votre code, ou en fonction de votre code possible, vous pouvez stocker des octets en prenant un opérateur unaire devant votre fonction! function () {/ * code * /} (); ~ function () {/ * code * /} (); - function () {/ * code * /} (); + function () {/ * code * /} (); // voici une autre variation, à partir de @kuvos - je ne suis pas sûr de la performance // implications, s'il en est d'utiliser le «nouveau mot-clé, mais informatique, mais tandis http://twitter.com/kuvos/status/18209252090847232New function () {/ * code * /} new function () {/ * code * /} () // n'a besoin que de parens si le passage des argumentsNotes importantes sur les supports
Dans certains cas, il n'est pas nécessaire d'entourer l'expression de la fonction lorsque des supports ambigus supplémentaires sont autour de l'expression de la fonction (car les supports sont déjà exprimés comme une expression), mais c'est toujours une bonne idée lorsque les supports sont utilisés pour appeler l'expression de la fonction.
Ces supports indiquent que l'expression de la fonction sera immédiatement appelée et que la variable stockera le résultat de la fonction, et non la fonction elle-même. Lorsqu'il s'agit d'une très longue expression de fonction, cela permet de gagner du temps que les personnes qui lisent votre code sans avoir à faire défiler vers le bas de la page pour voir si la fonction est appelée.
En règle générale, lorsque vous écrivez du code clair et clair, il est nécessaire d'empêcher JavaScript de lancer des erreurs, et il est également nécessaire d'empêcher d'autres développeurs de vous lancer des erreurs wtferror!
Enregistrez l'état de la fermeture
Tout comme lorsqu'une fonction est appelée par leur nom, les paramètres sont passés et lorsque l'expression de la fonction est appelée immédiatement, les paramètres sont passés. Une expression de fonction immédiatement appelée peut être utilisée pour verrouiller les valeurs et enregistrer efficacement l'état pour le moment, car toute fonction définie dans une fonction peut utiliser des paramètres et des variables transmises par la fonction extérieure (cette relation est appelée fermeture).
// Cela peut ne pas fonctionner comme vous le pensez, car la valeur de «I» n'est jamais verrouillée. // Inversement, lorsque chaque lien est cliqué (la boucle a été bien exécutée), donc le nombre total de tous les éléments apparaîtra, // parce que c'est la véritable valeur de `i 'pour le moment. var elems = document.getElementsByTagName ('a'); for (var i = 0; i <elems.length; i ++) {elems [i] .addeventListener ('clique La valeur «I» est verrouillée dans «LockedInIndex». // Lorsque la boucle est exécutée, bien que la valeur numérique de la valeur `i` soit la somme de tous les éléments, chaque fois que l'expression de la fonction est appelée, la valeur` LockedInIndex »dans iife est la valeur qui lui est transmise par` i`, donc lorsque le lien est cliqué, la valeur correcte est apparue. var elems = document.getElementsByTagName ('a'); for (var i = 0; i <elems.length; i ++) {(function (LockedInIndex) {elems [i] .AddeventListener ('clique }) (i);} // Vous pouvez également utiliser iife comme ce qui suit, simplement en utilisant des parenthèses pour inclure la fonction de traitement de clic, et à l'exclusion de l'intégralité de `ADDEVENTLISTENDER». // Peu importe dans quelle mesure, les deux exemples peuvent être verrouillés avec iife, mais j'ai constaté que l'exemple précédent est plus lisible var elems = document.getElementsByTagName ('a'); for (var i = 0; i <elems.length; i ++) {elems [i] .addeventListener ('click', (function (LockedIndex) {return function (e) {. alert ('je suis lien #' + LockedInIndex);};}) (i), false); }N'oubliez pas que dans ces deux derniers exemples, LockedInIndex peut accéder à I sans aucun problème, mais l'utilisation d'un identifiant nommé différent comme paramètre de la fonction peut rendre le concept plus facile à interpréter.
L'un des avantages les plus importants de l'exécution d'une fonction immédiatement est que même s'il n'est pas nommé ou anonyme, l'expression de la fonction peut être appelée immédiatement sans utiliser d'identifiant et une fermeture peut être utilisée sans contamination de la variable actuelle.
Quel est le problème de la fonction anonyme auto-exécutée ("fonction anonyme auto-exécutée")?
Vous avez vu qu'il est mentionné plusieurs fois, mais ce n'est toujours pas si clairement expliqué, je suggère de changer le terme en "expression de fonction immédiatement invoquée", ou, iife, si vous aimez l'abréviation.
Quelle est l'expression de la fonction immédiatement invoquée? Il fait une expression de fonction appelée immédiatement. C'est comme une expression de fonction qui vous amène à appeler.
Je pense que les membres de la communauté JavaScript devraient être en mesure d'accepter des termes, une expression de fonction immédiatement invoquée et de la vie dans leurs articles ou déclarations, car je pense qu'il est plus facile de comprendre le concept, et le terme "fonction anonyme auto-exécutant" n'est vraiment pas assez exact.
// Ce qui suit est une fonction auto-exécutante, qui appelle récursivement sa propre fonction foo () {foo ();}; // Il s'agit d'une fonction anonyme auto-exécutée. Parce qu'il n'a pas d'identifiant, il doit utiliser la propriété `arguments.callee` pour l'appeler lui-même var foo = function () {arguments.callee ();}; // Cela peut être considéré comme une fonction anonyme auto-exécutante, mais il est également possible si vous les remplacez par` foo` pour appeler var foo = fonction () {foo ();}; // des gens appellent la fonction ci-dessous ' Fonction anonyme comme celle-ci, même si elle n'est pas auto-exécutée car elle ne s'appelle pas. Ensuite, il a juste été appelé immédiatement. (function () {/ * code * /} ()); // L'ajout d'un identifiant à une expression de fonction (c'est-à-dire la création d'une fonction nommée) sera d'une grande aide à notre débogage. Une fois nommé, la fonction ne sera plus anonyme. (fonction foo () {/ * code * /} ()); // iifes peut également être exécuté par elle-même, bien que ce ne soit peut-être pas le modèle le plus utile (function () {arguments.callee ();} ()) (fonction foo () {foo ();} ()) // Une dernière chose à noter: cela entraînera une erreur dans Blackberry 5, car // à l'intérieur d'une fonction nommée, ce nom est un nom. Génial, hein? (Fonction foo () {foo ();} ());Espérons que l'exemple ci-dessus vous donnera une compréhension plus claire du terme auto-exécutant qui est quelque peu trompeur car il n'exécute pas sa propre fonction, bien que la fonction ait été exécutée. De même, il n'est pas nécessaire de souligner les fonctions anonymes, car l'expression de fonction immédiatement invoquée peut être une fonction nommée ou une fonction anonyme.
Dernier: mode module
Lorsque j'appelle une expression de fonction, si je me rappelle le motif du module au moins une fois, je l'ignorerai très probablement. Si vous n'avez pas le modèle de module en JavaScript, il est très similaire à mon exemple ci-dessous, mais la valeur de retour utilise un objet au lieu de la fonction.
var compter = (function () {var i = 0; return {get: function () {return i;}, set: function (val) {i = val;}, incrément: function () {return ++ i;}}} ()); Counter.get (); // 0 Counter.Set (3); Counter.Increment (); // 4 COMPREND.Increment (); // 5 Conuter.i; // Undefined (`i` n'est pas une propriété de l'objet retourné) i; // ReferenceError: I n'est pas défini (il n'existe qu'à l'intérieur de la fermeture)La méthode du mode module est non seulement assez puissante mais aussi simple. Avec très peu de code, vous pouvez utiliser efficacement la dénomination liée aux méthodes et aux attributs. Dans un objet, l'organisation de tous les codes de module minimise la pollution des variables globales et crée l'utilisation de variables.