Connaissez-vous la Déclaration de Fonction Expression vs Fonction, mais qu'est-ce que c'est? Expression de fonction nommée?

Duplication possible:
JavaScript: var functionName = function () {} vs function functionName () {}
Quelle est la différence entre une expression de fonction vs une déclaration en Javascript?

Je suis conscient des différences entre les déclarations de fonctions et les expressions, mais j'ai rencontré ce code impliquant le nom de la fonction et je veux comprendre ce qui se passe lorsque nous l'exécutons:

var abc = function def() { console.log("Wait! What??"); } 

Je sais que ce n'est pas un moyen de JavaScript, mais je veux juste connaître quelques choses:

  1. Qu'arrive-t-il à abc ? Pourquoi ça fonctionne? abc peut être appelé mais pas def , pourquoi?
  2. Est-ce une déclaration de fonction ou une expression?
  3. def est undefined – pourquoi? Si cela est censé être, y at-il des fuites de mémoire?
  4. Pourquoi abc.prototype est-ce que la fonction est abc.prototype ?

Merci

Qu'arrive-t-il à abc?

Il contient un objet fonction. Si vous ne faites rien avec cela, il sera prélevé.

Pourquoi ça fonctionne?

Pourquoi pas? Ce qui fonctionne"?

Abc peut être appelé mais pas défini, pourquoi?

Ce n'est vrai que de l'extérieur, et pas dans IE. Voir ci-dessous.

Est-ce une déclaration de fonction ou une expression?

C'est une expression de fonction. Vous pouvez facilement le voir car il fait partie d'une expression d'affectation; Les déclarations doivent toujours être au niveau supérieur (des fonctions ou du code global)

Def est indéfini – pourquoi?

Seulement de l'extérieur. Une expression de fonction ne crée pas de variables. "Def" est le nom de la fonction, et à l'intérieur de la fonction, il est également une référence à la fonction. Cela permet une récurrence, par exemple, sans utiliser de variables externes.

 var abc = function def() { def === abc; // true def.name; // "def" } abc(); def; // undefined 

Si cela est censé être, y at-il des fuites de mémoire?

Oui, dans Internet Explorer. Il crée deux fonctions distinctes à partir de ce code. Pour les détails, voir http://kangax.github.com/nfe/#jscript-bugs

Pourquoi abc.prototype est-ce que la fonction est définie?

Ce n'est pas. C'est juste un objet. Peut-être est-il montré avec ce nom dans votre console, comme appartient à une fonction nommée "def".

C'est une fonction nommée expressio n. Une utilisation possible pour cela pourrait être:

 var abc = function def() { def.test = 'Wait!'; //< sort of a static property console.log(def.test+" What??"); } 

Mais méfiez-vous .

C'est une expression fonctionnelle 2

Les expressions de fonctions peuvent également avoir des noms; Le nom de Function Expressions ne concerne que le champ de fonction 1 . (Depuis l'édition ECMAScript 5ème dépréciation arguments.callee , c'est la seule façon simple d'écrire une fonction "anonyme" récursive.)

Parce qu'il s'agit d' une expression fonctionnelle, le nom ne peut pas introduire 1 une nouvelle liaison dans la portée externe.

En outre, toutes les fonctions sont des objets en JavaScript. Dans f(..) , f est évalué avant qu'il soit "invoqué" avec (..) ; Si f n'a pas évalué une fonction, une erreur est lancée. C'est pourquoi les rappels, qui ne sont que des fonctions, peuvent être nommés par des variables et passés en tant que paramètres.

Vérifiez également l'hypothèse / assertion concernant le prototype:

 var abc = function def() {} abc.prototype === abc // -> false abc.name // -> "def" 

1 Voir la réponse de Bergi.

2 Comment savoir aisément quel est lequel?

Les règles de grammaire autorisent uniquement la function .. à être analysée comme une déclaration de fonction quand il s'agit d'un SourceElement bien que la plupart des moteurs analysent [incorrectement] une déclaration de fonction comme déclaration . Les productions SourceElement ne se produisent qu'au niveau supérieur du «bloc» d'un programme ou du «bloc» de haut niveau d'une fonction.

En tout cas, chaque fois qu'il y a une function .. qui apparaît dans un endroit nécessitant une expression , elle sera analysée en tant qu'expression fonctionnelle. Des exemples qui sont tous analysés comme expressions fonctionnelles:

 // Can only assign values: Statements do not have values! var f = function () {} var g = function gName () {} // see Bergi's answer // Can only pass values: Statements do not have values! doIt(function () {}) // callback / "anonymous function" // IIFE: Immediately-Invoked Function Expression ;(function () {})() // standard IIFE ;(function () {} ()) // alternative standard IIFE ;+function () {} () // curious way to write an IIFE // basically you can use any unary operator to turn it into an expression not only // + but also - ! ~ and so on which will modify the return value accordingly 

Le fait est que, dans chacun des cas ci-dessus, la function .. apparaît à un emplacement de grammaire nécessitant une expression et est ainsi analysée en tant qu'expression fonctionnelle. (Les points-virgules au début des lignes ci-dessus évitent une «ambiguïté» avec ASI, ce qui est nécessaire lors de l'écriture dans un style sans écolos comme je préfère.)

Toutefois. ;function () {} () et ;function f () {} () sont à la fois une syntaxe non valide – pourquoi? 😉

Votre exemple est une Expression fonctionnelle (nommée).

La différence Entre les deux est dans la façon dont le navigateur les charge.

Les déclarations de fonction sont chargées avant l'exécution de n'importe quel code.
Les expressions de fonction sont chargées uniquement lorsque l'interprète atteint cette ligne de code.

Ça signifie:

 abc(); var abc = function() { console.log("Wait! What??"); } 

Ne fonctionnera pas, mais:

 def(); function def() { console.log("Wait! What??"); } 

Volonté.

Maintenant dans votre exemple, vous pouvez accéder à def , mais seulement dans la fonction elle-même.

 var abc = function def() { console.log(def); } abc(); // Logs: //function def() { // console.log(def); //} 

C'est une expression de fonction nommée.

Contrairement aux déclarations de fonction, l'identificateur d'une expression de fonction n'est pas obligatoire.

Votre fonction def n'est pas immédiatement invoquée – toute la fonction passe à abc et doit être invoquée explicitement abc() .

§13 de la spécification ES5 indique comment les expressions de fonctions nommées sont construites. Lisez la troisième règle de production sur la façon dont les expressions de fonctions nommées sont construites.

REMARQUE L'identifiant dans une expression Function peut être référencé à partir de la FunctionBody FunctionExpression pour permettre à la fonction de s'appeler lui-même récursivement. Toutefois, contrairement à FunctionDeclaration, l'identificateur dans un FunctionExpression ne peut être référencé et n'affecte pas la portée entourant l'expression FunctionExpression.

Tous les navigateurs récents fonctionnent correctement, de sorte que vous ne devez pas vous inquiéter et les fuites de mémoire ou d'autres éléments étranges (la mauvaise manipulation n'est que dans l'ancien IE <= 8).