Je lisais des articles sur les fermetures et je l'ai vu partout, mais il n'y a pas d'explication claire sur le fonctionnement - à chaque fois, on m'a simplement dit de l'utiliser ...:
// Create a new anonymous function, to use as a wrapper
(function(){
// The variable that would, normally, be global
var msg = "Thanks for visiting!";
// Binding a new function to a global object
window.onunload = function(){
// Which uses the 'hidden' variable
alert( msg );
};
// Close off the anonymous function and execute it
})();
Ok, je vois que nous allons créer une nouvelle fonction anonyme puis l'exécuter. Donc, après cela, ce code simple devrait fonctionner (et il fonctionne):
(function (msg){alert(msg)})('SO');
Ma question est quel genre de magie se produit ici? J'ai pensé que quand j'ai écrit:
(function (msg){alert(msg)})
alors une nouvelle fonction sans nom serait créée comme la fonction "" (msg) ...
mais alors pourquoi ça ne marche pas?
(function (msg){alert(msg)});
('SO');
Pourquoi doit-il être dans la même ligne?
Pourriez-vous s'il vous plaît me pointer quelques messages ou me donner une explication?
(function (msg){alert(msg)})('SO');
fonctionne entièrement seule. Cela n'a rien à voir avec l'autre fonction anonyme que vous avez publiée avant. Ce sont deux fonctions anonymes complètement distinctes. Vous devez appeler une fonction anonyme immédiatement car elle n'a pas de nom et ne peut plus être référencée par la suite.Réponses:
Déposez le point-virgule après la définition de la fonction.
Ci-dessus devrait fonctionner.
Page DEMO: https://jsfiddle.net/e7ooeq6m/
J'ai discuté de ce type de modèle dans ce post:
jQuery et $ questions
ÉDITER:
Si vous regardez la spécification du script ECMA , il existe 3 façons de définir une fonction. (Page 98, section 13 Définition de la fonction)
1. Utilisation du constructeur de fonction
2. Utilisation de la déclaration de fonction.
3. Expression de fonction
Vous pouvez donc vous demander quelle est la différence entre la déclaration et l'expression?
De la spécification ECMA Script:
Si vous remarquez, «identifiant» est facultatif pour l'expression de fonction. Et lorsque vous ne donnez pas d'identifiant, vous créez une fonction anonyme. Cela ne signifie pas que vous ne pouvez pas spécifier un identifiant.
Cela signifie que le suivi est valide.
Un point important à noter est que vous ne pouvez utiliser «mySum» qu'à l'intérieur du corps de la fonction mySum, pas à l'extérieur. Voir l'exemple suivant:
Démo en direct
Comparez cela à
Armés de ces connaissances, essayons d'analyser votre code.
Lorsque vous avez du code comme,
Vous avez créé une expression de fonction. Et vous pouvez exécuter cette expression de fonction en la mettant entre parenthèses.
la source
Cela s'appelle une fonction auto-invoquée.
Ce que vous faites lorsque vous appelez
(function(){})
renvoie un objet fonction. Lorsque vous y ajoutez()
, il est invoqué et tout ce qui se trouve dans le corps est exécuté. Le;
dénote la fin de l'instruction, c'est pourquoi la 2e invocation échoue.la source
Une chose que j'ai trouvée confuse est que les "()" regroupent les opérateurs.
Voici votre fonction déclarée de base.
Ex. 1:
Les fonctions sont des objets et peuvent être regroupées. Jetons donc des parenthèses autour de la fonction.
Ex. 2:
Maintenant, au lieu de déclarer et d'appeler immédiatement la même fonction, nous pouvons utiliser la substitution de base pour la déclarer comme nous l'appelons.
Ex. 3.
Enfin, nous n'avons pas besoin de ce truc supplémentaire parce que nous n'utilisons pas le nom pour l'appeler! Les fonctions peuvent être anonymes.
Ex. 4.
Pour répondre à votre question, reportez-vous à l'exemple 2. Votre première ligne déclare une fonction sans nom et la regroupe, mais ne l'appelle pas. La deuxième ligne regroupe une chaîne. Les deux ne font rien. (Premier exemple de Vincent.)
Mais
la source
Une fonction anonyme n'est pas une fonction avec le nom "". C'est simplement une fonction sans nom.
Comme toute autre valeur en JavaScript, une fonction n'a pas besoin d'un nom pour être créée. Bien qu'il soit beaucoup plus utile de le lier à un nom comme n'importe quelle autre valeur.
Mais comme toute autre valeur, vous souhaitez parfois l'utiliser sans la lier à un nom. C'est le modèle auto-invocateur.
Voici une fonction et un nombre, non liés, ils ne font rien et ne peuvent jamais être utilisés:
Nous devons donc les stocker dans une variable pour pouvoir les utiliser, comme toute autre valeur:
Vous pouvez également utiliser du sucre syntaxique pour lier la fonction à une variable:
Mais si les nommer n'est pas requis et entraînerait plus de confusion et moins de lisibilité, vous pouvez simplement les utiliser immédiatement.
Ici, ma fonction et mes nombres ne sont pas liés à une variable, mais ils peuvent toujours être utilisés.
Dit comme ça, on dirait que la fonction auto-invoquante n'a aucune valeur réelle. Mais vous devez garder à l'esprit que le délimiteur de portée JavaScript est la fonction et non le bloc ({}).
Ainsi, une fonction auto-invoquante a en fait la même signification qu'un bloc C ++, C # ou Java. Ce qui signifie que la variable créée à l'intérieur ne "fuira" pas en dehors de la portée. Ceci est très utile en JavaScript afin de ne pas polluer la portée globale.
la source
C'est juste comment JavaScript fonctionne. Vous pouvez déclarer une fonction nommée:
Et appelez ça:
Ou, vous pouvez déclarer une fonction anonyme:
Et appelez ça:
Ou, vous ne pouvez tout simplement jamais lier la fonction à un nom:
Les fonctions peuvent également renvoyer des fonctions:
Cela ne vaut rien que les variables définies avec "var" dans le corps de
make_foo
soient fermées par chaque fonction retournée parmake_foo
. Il s'agit d'une fermeture et cela signifie que toute modification apportée à la valeur par une fonction sera visible par une autre.Cela vous permet d'encapsuler des informations, si vous le souhaitez:
C'est à quel point presque tous les langages de programmation, à l'exception de Java, fonctionnent.
la source
Le code que vous montrez,
se composent de deux déclarations. La première est une expression qui produit un objet fonction (qui sera ensuite récupéré car il n'est pas enregistré). La seconde est une expression qui produit une chaîne. Pour appliquer la fonction à la chaîne, vous devez soit passer la chaîne comme argument à la fonction lors de sa création (que vous montrez également ci-dessus), soit vous devrez réellement stocker la fonction dans une variable, afin de pouvoir l'appliquer ultérieurement, à votre guise. Ainsi:
Notez qu'en stockant une fonction anonyme (une fonction lambda) dans une variable, vous lui donnez effectivement un nom. Par conséquent, vous pouvez tout aussi bien définir une fonction régulière:
la source
En résumé des commentaires précédents:
lorsqu'il n'est pas affecté à une variable, renvoie une erreur de syntaxe. Le code est analysé comme une instruction de fonction (ou définition), ce qui rend les parenthèses fermantes syntaxiquement incorrectes. L'ajout de parenthèses autour de la partie fonction indique à l'interpréteur (et au programmeur) qu'il s'agit d'une expression de fonction (ou invocation), comme dans
Il s'agit d'une fonction auto-invoquée, ce qui signifie qu'elle est créée de manière anonyme et s'exécute immédiatement car l'invocation se produit sur la même ligne où elle est déclarée. Cette fonction d'auto-invocation est indiquée avec la syntaxe familière d'appeler une fonction sans argument, plus ajouté entre parenthèses autour du nom de la fonction:
(myFunction)();
.Il existe une bonne syntaxe de la fonction JavaScript de discussion SO .
la source
Cette réponse n'est pas strictement liée à la question, mais vous pourriez être intéressé de découvrir que ce type de fonctionnalité de syntaxe n'est pas spécifique aux fonctions. Par exemple, nous pouvons toujours faire quelque chose comme ceci:
Lié aux fonctions. Comme ce sont des objets, qui héritent de Function.prototype, nous pouvons faire des choses comme:
Et vous savez, nous n'avons même pas besoin d'entourer les fonctions de parenthèses pour les exécuter. Quoi qu'il en soit, tant que nous essayons d'assigner le résultat à une variable.
Une autre chose que vous pouvez faire avec les fonctions, dès que vous les déclarez, est d'invoquer l'
new
opérateur sur elles et d'obtenir un objet. Les éléments suivants sont équivalents:la source
Il existe une autre propriété JavaScript. Si vous souhaitez appeler la même fonction anonyme de manière récursive.
la source
Ma compréhension de la question du demandeur est telle que:
Comment fonctionne cette magie:
J'ai peut-être tort. Cependant, la pratique habituelle que les gens connaissent est:
La raison est telle que JavaScript entre parenthèses AKA
()
, ne peut pas contenir d'instructions et lorsque l'analyseur rencontre le mot-clé de fonction, il sait l'analyser en tant qu'expression de fonction et non en tant que déclaration de fonction.Source: article de blog Expression de la fonction immédiatement invoquée (IIFE)
la source
exemples sans crochets:
(c'est la seule utilisation réelle de void, afaik)
ou
ou
travailler aussi. le
void
fait évaluer l'expression, ainsi que l'affectation et le coup. le dernier travaille avec~
,+
,-
,delete
,typeof
, certains opérateurs unaires (void
est un aussi). ne travaillent pas sont de couse++
, en--
raison de l'exigence d'une variable.le saut de ligne n'est pas nécessaire.
la source
delete
fonctionne. même avec'use strict';
. cela fonctionne aussi:delete (3 + 4);
Il s'agit d'une fonction anonyme auto-exécutable. Le premier ensemble de crochets contient les expressions à exécuter et le deuxième ensemble de crochets exécute ces expressions.
Peter Michaux discute de la différence dans une importante paire de parenthèses .
Il s'agit d'une construction utile lorsque vous essayez de masquer des variables de l'espace de noms parent. Tout le code de la fonction est contenu dans la portée privée de la fonction, ce qui signifie qu'il n'est pas du tout accessible de l'extérieur de la fonction, ce qui la rend vraiment privée.
Voir:
la source
Un autre point de vue
Tout d'abord, vous pouvez déclarer une fonction anonyme:
Ensuite, vous l'appelez:
Parce que foo = function (msg) {alert (msg);} vous pouvez donc remplacer foo comme:
Mais vous devez encapsuler l'intégralité de votre fonction anonyme dans une paire d'accolades pour éviter une erreur de syntaxe lors de la déclaration de la fonction lors de l'analyse. Ensuite nous avons,
De cette façon, c'est facile à comprendre pour moi.
la source
Quand vous l'avez fait:
Vous avez terminé la fonction avant à
('SO')
cause du point-virgule. Si vous écrivez juste:Ça va marcher.
Exemple de travail: http://jsfiddle.net/oliverni/dbVjg/
la source
La simple raison pour laquelle cela ne fonctionne pas n'est pas due à l'
;
indication de la fin de la fonction anonyme. C'est parce que sans la()
fin d'un appel de fonction, ce n'est pas un appel de fonction. C'est,Si vous appelez
result = help();
c'est un appel à une fonction et retournera vrai.Si vous appelez,
result = help;
ce n'est pas un appel. Il s'agit d'une affectation dans laquelle l'aide est traitée comme des données à affecter au résultat.Ce que vous avez fait était de déclarer / instancier une fonction anonyme en ajoutant le point-virgule,
puis j'ai essayé de l'appeler dans une autre instruction en utilisant juste des parenthèses ... Évidemment parce que la fonction n'a pas de nom, mais cela ne fonctionnera pas:
L'interprète voit les parenthèses sur la deuxième ligne comme une nouvelle instruction / instruction, et donc cela ne fonctionne pas, même si vous l'avez fait comme ceci:
Cela ne fonctionne toujours pas, mais cela fonctionne lorsque vous supprimez le point-virgule car l'interpréteur ignore les espaces blancs et les chariots et voit le code complet comme une seule instruction.
Conclusion: un appel de fonction n'est pas un appel de fonction sans la
()
fin sauf si dans des conditions spécifiques telles que l'appel d'une autre fonction, c'est-à-dire que onload = 'help' exécuterait la fonction d'aide même si les parenthèses n'étaient pas incluses. Je crois que setTimeout et setInterval autorisent également ce type d'appel de fonction, et je crois également que l'interprète ajoute de toute façon les parenthèses en arrière-plan, ce qui nous ramène à "un appel de fonction n'est pas un appel de fonction sans les parenthèses".la source
Il s'agit d'une méthode courante d'utilisation d'une fonction anonyme comme fermeture que de nombreux frameworks JavaScript utilisent.
Cette fonction est appelée automatiquement lorsque le code est compilé.
S'il est placé
;
à la première ligne, le compilateur l'a traité comme deux lignes différentes. Vous ne pouvez donc pas obtenir les mêmes résultats que ci-dessus.Cela peut également s'écrire:
Pour plus de détails, consultez les fonctions JavaScript / anonymes .
la source
Les fonctions anonymes sont des fonctions qui sont déclarées dynamiquement lors de l'exécution. Elles sont appelées fonctions anonymes car elles ne reçoivent pas de nom de la même manière que les fonctions normales.
Les fonctions anonymes sont déclarées à l'aide de l'opérateur de fonction au lieu de la déclaration de fonction. Vous pouvez utiliser l'opérateur de fonction pour créer une nouvelle fonction partout où il est valide pour mettre une expression. Par exemple, vous pouvez déclarer une nouvelle fonction en tant que paramètre d'un appel de fonction ou attribuer une propriété d'un autre objet.
Voici un exemple typique d'une fonction nommée:
fonction flyToTheMoon () {alert ("Zoom! Zoom! Zoom!"); } Voler vers la lune(); Voici le même exemple créé en tant que fonction anonyme:
var flyToTheMoon = function () {alert ("Zoom! Zoom! Zoom!"); } Voler vers la lune();
Pour plus de détails, veuillez lire ici:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
la source
L'IIFE compartimente simplement la fonction et masque la
msg
variable afin de ne pas «polluer» l'espace de noms global. En réalité, restez simple et faites comme ci-dessous, sauf si vous créez un site Web d'un milliard de dollars.Vous pouvez nommer votre
msg
propriété en utilisant un modèle de module révélateur comme:la source
Les fonctions anonymes sont censées être des transactions ponctuelles où vous définissez une fonction à la volée afin qu'elle génère une sortie de votre part à partir d'une entrée que vous fournissez. Sauf que vous n'avez pas fourni d'entrée. Au lieu de cela, vous avez écrit quelque chose sur la deuxième ligne («SO»); - une déclaration indépendante qui n'a rien à voir avec la fonction. Qu'est-ce que vous attendiez? :)
la source
var foo = function() {};
. Mais tout le reste va bien.