web-dev-qa-db-fra.com

Pourquoi utiliser des expressions de fonction nommées?

Nous avons deux manières différentes de faire une expression de fonction en JavaScript:

Expression de fonction nommée (NFE)

var boo = function boo () {
  alert(1);
};

Expression de fonction anonyme :

var boo = function () {
  alert(1);
};

Et les deux peuvent être appelés avec boo();. Je ne vois vraiment pas pourquoi/quand utiliser des fonctions anonymes ni quand utiliser des expressions de fonction nommées. Quelle différence y a-t-il entre eux?

81
Afshin Mehrabani

Dans le cas de l'expression de fonction anonyme, la fonction est anonymous - littéralement, elle n'a pas de nom. La variable à laquelle vous l'assignez a un nom, mais pas la fonction. (Mise à jour: cela était vrai jusqu'à ES5. À compter de ES2015 [alias ES6], une fonction créée avec une expression anonyme reçoit un vrai nom, continuez à la lecture ...)

Les noms sont utiles. Les noms peuvent être vus dans les traces de pile, les piles d'appels, les listes de points d'arrêt, etc. Les noms sont un Good Thing ™.

Vous devez vous méfier des expressions de fonction nommées dans les anciennes versions de IE (IE8 et versions ultérieures), car IE crée par erreur deux objets fonction complètement séparés à deux moments complètement différents (plus de détails dans mon article de blog Double prendre ). Si vous devez prendre en charge IE8, il est probablement préférable de vous en tenir aux expressions de fonction anonymes ou à la fonction déclarations, mais en évitant les expressions de fonction nommées.

Depuis ES2015, cependant, de nombreuses expressions de fonction "anonymes" créent des fonctions avec des noms, ce qui a été précédé par divers moteurs JavaScript modernes, assez intelligents pour inférer des noms à partir du contexte. Dans ES2015, votre expression de fonction anonyme génère une fonction nommée boo. Ceci est éparpillé tout au long de la spécification plutôt que d'être défini à un endroit avec un tas de règles: Recherchez les occurrences de "SetFunctionName", actuellement trouvé dans:

La version courte est essentiellement chaque fois qu'une expression de fonction anonyme apparaît à droite d'une tâche telle qu'une affectation ou une initialisation, telle que:

var boo = function() { /*...*/ };

(ou ce pourrait être let ou const plutôt que var), ou

var obj = {
    boo: function() { /*...*/ }
};

ou

doSomething({
    boo: function() { /*...*/ }
});

(ces deux derniers sont vraiment la même chose), la fonction résultante aura un nom (boo, dans les exemples).

Il existe une exception importante et intentionnelle: l'affectation à une propriété sur un objet existant:

obj.boo = function() { /*...*/ }; // <== Does not get a name

Cela était dû aux craintes de fuite d'informations soulevées lors de l'ajout de la nouvelle fonctionnalité. détails dans ma réponse à une autre question ici .

78
T.J. Crowder

Nommer des fonctions est utile s’ils doivent se référencer eux-mêmes (par exemple pour des appels récursifs). En effet, si vous transmettez directement une expression de fonction littérale en tant qu'argument à une autre fonction, cette expression de fonction ne peut pas se référencer directement en mode strict ES5, à moins d'être nommée.

Par exemple, considérons ce code:

setTimeout(function sayMoo() {
    alert('MOO');
    setTimeout(sayMoo, 1000);
}, 1000);

Il serait impossible d'écrire ce code aussi clairement si l'expression de fonction transmise à setTimeout était anonyme; nous aurions besoin de l'affecter à une variable avant l'appel setTimeout. De cette façon, avec une expression de fonction nommée, elle est légèrement plus courte et plus nette.

Il était historiquement possible d'écrire un tel code même en utilisant une expression de fonction anonyme, en exploitant arguments.callee ...

setTimeout(function () {
    alert('MOO');
    setTimeout(arguments.callee, 1000);
}, 1000);

... mais arguments.callee est obsolète et est strictement interdit en mode strict ES5. C'est pourquoi MDN conseille:

Évitez d’utiliser arguments.callee() de en attribuant un nom aux expressions de fonction ou d’utiliser une déclaration de fonction dans laquelle une fonction doit s’appeler elle-même.

(c'est moi qui souligne)

21
Mark Amery

Si une fonction est spécifiée en tant qu'expression de fonction, vous pouvez lui attribuer un nom.

Il ne sera disponible que dans la fonction (sauf IE8-).

var f = function sayHi(name) {
  alert( sayHi ); // Inside the function you can see the function code
};

alert( sayHi ); // (Error: undefined variable 'sayHi')

Ce nom est destiné à un appel de fonction récursif fiable, même s'il est écrit dans une autre variable.

De plus, le nom NFE (expression de fonction nommée) PEUT être remplacé par la méthode Object.defineProperty(...) comme suit:

var test = function sayHi(name) {
  Object.defineProperty(test, 'name', { value: 'foo', configurable: true });
  alert( test.name ); // foo
};

test();

Remarque: cela ne peut pas être fait avec la déclaration de fonction. Ce nom de fonction interne "spécial" est spécifié uniquement dans la syntaxe Expression de fonction.

3
Roman

Il est préférable d’utiliser des expressions de fonction nommée lorsque vous souhaitez pouvoir référencer la fonction en question sans avoir à vous fier à des fonctionnalités obsolètes telles que arguments.callee.

1
Sudhir Bastakoti

Vous devez toujours utiliser les expressions de fonction NAMED.

  1. Vous pouvez utiliser le nom de cette fonction lorsque vous avez besoin de récursivité.

2.Anonymous Functions n’aide pas lors du débogage car vous ne pouvez pas voir le nom de la fonction qui pose problème.

3.Lorsque vous ne nommez pas une fonction, il est plus difficile ensuite de comprendre ce qu'elle fait. Lui attribuer un nom facilite sa compréhension.

var foo = function bar() {
 //some code...
};
foo();
bar(); // Error!

Ici, par exemple, comme la barre de nom est utilisée dans une expression de fonction, elle n'est pas déclarée dans la portée externe. Avec les expressions de fonction nommées, le nom de l'expression de fonction est inclus dans sa propre portée.

0
lux