Nous avons deux méthodes différentes pour 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 je devrais utiliser des fonctions anonymes et quand je devrais utiliser des expressions de fonction nommées. Quelle différence y a-t-il entre eux?
javascript
function
anonymous-function
function-expression
Afshin Mehrabani
la source
la source
Réponses:
Dans le cas de l'expression de fonction anonyme, la fonction est anonyme - littéralement, elle n'a pas de nom. La variable à laquelle vous l'affectez a un nom, mais pas la fonction. (Mise à jour: c'était vrai via ES5. Depuis ES2015 [aka ES6], souvent une fonction créée avec une expression anonyme obtient un vrai nom [mais pas un identifiant automatique], lisez la suite ...)
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 une bonne chose ™.
(Vous deviez vous méfier des expressions de fonction nommées dans les anciennes versions d'IE [IE8 et versions antérieures], car elles créaient par erreur deux objets de fonction complètement séparés à deux moments complètement différents [plus dans mon article de blog Double prise ]. Si vous devez supporte IE8 [!!], il est probablement préférable de s'en tenir aux expressions de fonction anonymes ou aux déclarations de fonction , mais évitez les expressions de fonction nommées.)
Une chose clé à propos d'une expression de fonction nommée est qu'elle crée un identificateur dans la portée avec ce nom pour la fonction dans le corps de la fonction:
Depuis ES2015, cependant, beaucoup d'expressions de fonction «anonymes» créent des fonctions avec des noms, et cela a été précédé par divers moteurs JavaScript modernes qui étaient assez intelligents pour déduire des noms à partir du contexte. Dans ES2015, votre expression de fonction anonyme entraîne une fonction avec le nom
boo
. Cependant, même avec la sémantique ES2015 +, l'identifiant automatique n'est pas créé:L'affectation du nom de la fonction est effectuée avec l' opération abstraite SetFunctionName utilisée dans diverses opérations de la spécification.
La version courte est essentiellement à chaque fois qu'une expression de fonction anonyme apparaît sur le côté droit de quelque chose comme une affectation ou une initialisation, comme:
(ou cela pourrait être
let
ouconst
plutôt quevar
) , ouou
(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'attribution à une propriété sur un objet existant:
Cela était dû aux problèmes de fuite d'informations soulevés lorsque la nouvelle fonctionnalité était en cours d'ajout; détails dans ma réponse à une autre question ici .
la source
new
opérateur (donner à toutes ces fonctions des noms rend la.constructor
propriété plus utile lors du débogage pour déterminer ce que le diable un objet est une instance de), et pour les littéraux de fonction passés directement dans une fonction sans avoir été préalablement affectés à une propriété ou à une variable (par exemplesetTimeout(function () {/*do stuff*/});
). Même Chrome les montre à(anonymous function)
moins que vous ne les aidiez en les nommant.setTimeout
exemple ne saisissait pas le nom de l'argument formel déclaré poursetTimeout
, s'il en avait un. :-) Mais oui, les NFE sont vraiment utiles si vous savez que vous n'aurez pas affaire à d'anciens navigateurs qui en font un hachage.La dénomination des fonctions est utile si elles ont besoin de se référencer elles-mêmes (par exemple pour les appels récursifs). En effet, si vous passez une expression de fonction littérale comme argument directement à une autre fonction, cette expression de fonction ne peut pas se référencer directement en mode strict ES5 à moins qu'elle ne soit nommée.
Par exemple, considérez ce code:
Il serait impossible d'écrire ce code aussi proprement si l'expression de fonction transmise
setTimeout
était anonyme; nous aurions besoin de l'attribuer à une variable à la place avant l'setTimeout
appel. De cette façon, avec une expression de fonction nommée, est légèrement plus courte et plus nette.Il était historiquement possible d'écrire du code comme celui-ci même en utilisant une expression de fonction anonyme, en exploitant
arguments.callee
...... mais
arguments.callee
est obsolète, et est carrément interdit en mode strict ES5. C'est pourquoi MDN conseille:(c'est moi qui souligne)
la source
Si une fonction est spécifiée en tant qu'expression de fonction, elle peut recevoir un nom.
Il ne sera disponible que dans la fonction (sauf IE8-).
Ce nom est destiné à un appel de fonction récursive fiable, même s'il est écrit dans une autre variable.
De plus, le nom NFE (Named Function Expression) PEUT être écrasé par la
Object.defineProperty(...)
méthode suivante: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 de l'expression de fonction.
la source
Vous devez toujours utiliser des expressions de fonction nommées , c'est pourquoi:
Vous pouvez utiliser le nom de cette fonction lorsque vous avez besoin de récursivité.
Les fonctions anonymes n'aident pas lors du débogage car vous ne pouvez pas voir le nom de la fonction qui pose des problèmes.
Lorsque vous ne nommez pas une fonction, plus tard, il est plus difficile de comprendre ce qu'elle fait. Lui donner un nom le rend plus facile à comprendre.
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.
la source
Il est préférable d'utiliser des expressions de fonction nommées lorsque vous souhaitez pouvoir référencer la fonction en question sans avoir à vous fier à des fonctionnalités obsolètes telles que
arguments.callee
.la source