30 votes

Vous connaissez l'expression de fonction JavaScript et la déclaration de fonction, mais qu'est-ce que c'est ? Expression de fonction nommée ?

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

Je connais les différences entre les déclarations de fonction et les expressions, mais je suis tombé sur ce code impliquant un nom de 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 une façon de faire du JavaScript, mais je veux juste savoir quelques petites choses :

  1. Qu'advient-il des abc ? Pourquoi cela fonctionne-t-il ? abc peut être appelé, mais pas def Pourquoi ?
  2. S'agit-il d'une déclaration de fonction ou d'une expression ?
  3. def es undefined - pourquoi ? S'il est censé l'être, existe-t-il des fuites de mémoire ?
  4. Pourquoi la abc.prototype est une fonction def ?

Remerciements

11voto

Bergi Points 104242

Qu'advient-il d'abc ?

Il contient un objet fonction. Si vous ne faites rien avec lui, il sera ramassé.

Pourquoi cela fonctionne-t-il ?

Pourquoi pas ? Qu'est-ce qui "marche" ?

abc peut être appelé mais pas def, pourquoi ?

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

S'agit-il d'une déclaration de fonction ou d'une expression ?

Il s'agit d'une expression fonctionnelle. Vous pouvez facilement voir que cela 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 l'expression nom de la fonction, et à l'intérieur de la fonction, il s'agit également d'une référence à la fonction. Cela permet, par exemple, la récursivité sans utiliser de variables extérieures.

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

S'il est censé l'être, y a-t-il des fuites de mémoire ?

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

Pourquoi abc.prototype est une fonction def ?

Ce n'est pas le cas. Ce n'est qu'un objet. Il est peut-être affiché avec ce nom dans votre console, comme appartenant à une fonction nommée "def".

5voto

KooiInc Points 38845

Il s'agit d'un fonction nommée expressio n. Une utilisation possible de ce terme pourrait être :

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

Mais se méfier .

2voto

Il s'agit d'un Fonction Expression 2

Expressions de fonctions peut ont également des noms ; les noms des expressions de fonction n'ont de portée que dans le corps de la fonction 1 . (Depuis que la 5e édition d'ECMAScript a déprécié l'option arguments.callee c'est la seule façon simple d'écrire une fonction récursive "anonyme").

Parce qu'il est une expression de fonction, le nom ne peut pas 1 introduire une nouvelle liaison dans la portée extérieure.

En outre, tous sont des objets en JavaScript. Dans les f(..) , f est évaluée avant il est "invoqué" avec (..) ; si f n'a pas été évaluée comme une fonction, une erreur est levé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/l'affirmation concernant le prototype :

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

1 Voir la réponse de Bergi.

2 Comment distinguer facilement les uns des autres ?

Les règles de grammaire sólo permettre function .. d'être analysé comme une déclaration de fonction alors qu'il s'agit d'un Élément source bien que la plupart des moteurs continuent d'analyser [incorrectement] une déclaration de fonction en tant que Déclaration . Productions SourceElement sólo se produisent au niveau du "bloc" supérieur d'un programme ou du "bloc" supérieur d'une fonction.

En tout état de cause, chaque fois qu'il y a un function .. qui apparaît dans un lieu qui exige un Expression , il volonté est analysé comme une expression de fonction. Les exemples qui sont tous analysées comme des expressions de fonction :

// 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 qu'en tous un seul des cas susmentionnés, function .. apparaît à un endroit de la grammaire exigeant une expression et est donc analysée comme une expression de fonction. (Les points-virgules au début des lignes ci-dessus évitent toute "ambiguïté" avec l'ASI, ce qui est nécessaire lorsque l'on écrit dans un style sans points-virgules, comme je le préfère).

Cependant. ;function () {} () y ;function f () {} () sont tous deux des syntaxes invalides - pourquoi ? ;-)

2voto

Christoph Points 23467

Il s'agit d'une expression de fonction nommée.

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

Votre fonction def n'est pas immédiatement invoquée - la fonction entière est transmise à la fonction abc et doit être invoqué de manière explicite 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.

NOTE L'identificateur dans un FunctionExpr à l'intérieur du corps de la fonction de la FunctionExpression pour permettre à la fonction de de s'appeler elle-même de manière récursive. Cependant, contrairement à une FunctionDeclaration, l'identificateur Identifier dans une FunctionExpression ne peut pas être référencé et n'affecte pas la portée de la FunctionExpression. et n'affecte pas la portée de l'expression de fonction.

Tous les navigateurs récents gèrent cela correctement, vous n'avez donc pas à vous soucier des fuites de mémoire ou d'autres choses bizarres (la gestion incorrecte ne concerne que les anciens IE <=8).

1voto

Cerbrus Points 20704

Votre exemple est une expression de fonction (nommée).

La différence entre les deux réside dans la manière dont le navigateur les charge.

Les déclarations de fonctions sont chargées avant tout code est exécuté.
Les expressions de fonction ne sont chargées que quand l'interprète parvient à ce que ligne de code.

Cela signifie que :

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

Cela ne fonctionnera pas, mais.. :

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

Le testament.

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

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X