2010-11-28 3 views
1

Je viens de lire l'article de Ben Alman sur Immediately-Invoked Function Expressions et se sont interrogés sur cette partie, où il l'introduction d'expressions de la fonction et les fermetures (pas vraiment liés encore IIFEs):Pourquoi existe-t-il deux syntaxes différentes pour appeler des expressions de fonction anonymes?

// ...doesn't it stand to reason that the function expression itself can 
// be invoked, just by putting() after it? 

function(){ /* code goes here */ }(); 

// This works! Well, almost. A minor JavaScript syntax issue actually 
// requires that ambiguity between function declarations and function 
// expressions be eliminated, which can be done by wrapping the function 
// expression in parens. 

// The following pattern is used universally to create an anonymous 
// closure with "privacy": 

(function(){ /* code goes here */ })(); 

// This parens syntax is also valid (I prefer the previous version): 

(function(){ /* code goes here */ }()); 

Cette dernière partie m'a frappé. Quelqu'un peut-il expliquer pourquoi il existe deux versions syntaxiques différentes pour invoquer des expressions de fonction?

Était-ce la syntaxe introduit consciemment juste pour appeler les fermetures anonymes? Ou est-ce un sous-produit d'une autre propriété syntaxique?

Pourquoi la deuxième version fonctionne de toute façon? Le premier a un sens pour moi du point de vue de l'analyseur. La première paire de parens évalue un objet fonction, la deuxième paire invoque cet objet fonction. Mais le second? Cela ne semble pas résoudre l'ambiguïté syntaxique mentionnée.

Quelqu'un peut-il me dire ce qui me manque ici?

Répondre

3

Tout cela arrive parce que JavaScript a deux contextes d'analyse syntaxique: expression et déclaration. L'écriture function foo() {} au niveau de l'instruction définit la fonction foo dans ce champ, alors que function foo() {} au niveau d'expression évalue une nouvelle fonction anonyme (qui peut s'appeler récursive comme foo).

Ainsi, chaque fois que cette construction est rencontrée, l'analyseur doit déterminer si elle est à l'expression ou le niveau de l'instruction. Par défaut, il suppose être au niveau de l'instruction, à moins d'être convaincu autrement. Les parenthèses sont une manière syntaxique de dire "c'est une expression".

Ainsi, l'écriture (function() {}) provoque l'analyseur pour traiter la fonction comme une expression. Puisque les expressions ne peuvent contenir que d'autres expressions (aucune instruction), il s'ensuit également que si vous écrivez (something-that-contains function(){} and-other-stuff) alors la fonction sera toujours traitée comme une expression.

+0

Excellente réponse. Juste ce que je cherchais (mais je ne pouvais pas penser à moi-même). :) Merci! –

1

La seconde fonctionne parce qu'une expression entre parenthèses ne peut pas être interprétée comme une déclaration de fonction (elle doit donc être une expression de fonction, résolvant le problème d'ambiguïté avec la première expression d'origine).

Questions connexes