Préface
Dans ECMAScript, il existe deux méthodes les plus couramment utilisées pour créer des objets de fonction, à savoir utiliser des expressions de fonction ou utiliser des déclarations de fonction. À cet égard, la spécification ECMAScript indique clairement que les déclarations de fonction doivent toujours porter un identifiant, ce que nous appelons le nom de la fonction et que les expressions de fonction peuvent être omises. Jetons un coup d'œil à l'introduction détaillée des différences entre les deux.
Qu'est-ce que la déclaration de fonction?
La déclaration de fonction peut définir les variables de fonction nommées sans attribuer de valeurs aux variables. La déclaration de fonction est une structure indépendante qui ne peut pas être imbriquée dans les modules non fonctionnels. Il peut être comparé à la déclaration variable. Tout comme la déclaration variable doit commencer par "var", la déclaration de fonction doit commencer par "fonction".
Par exemple
fonction bar () {return 3;}ECMA 5 (13.0) Définition Syntaxe:
function Identifier ( FormalParameterList[opt] ) { FunctionBody }
Les noms de fonction sont disponibles dans leur propre portée et portée parent (sinon la fonction ne sera pas disponible).
fonction bar () {return 3;} bar () // 3bar // fonctionQu'est-ce que l'expression de la fonction?
L'expression de la fonction définit une fonction comme faisant partie d'une instruction d'expression (généralement une affectation variable). Les fonctions définies par l'expression de la fonction peuvent être nommées ou anonymes. L'expression de la fonction ne peut pas commencer par la "fonction" (les exemples de point d'auto suivant doivent être enfermés entre parenthèses).
Par exemple
// fonction anonyme ExpressionVar a = function () {return 3;} // nommé function expressionvar a = function bar () {return 3;} // invocing function expression (function sayshello () {alert ("hello!");}) ();ECMA 5 (13.0) Définition Syntaxe:
function Identifieropt ( FormalParameterList[opt] ) { FunctionBody }
(Cette définition semble incomplète car elle ignore une condition: l'instruction périphérique est une expression et ne commence pas par "fonction")
Les noms de fonction (le cas échéant) ne sont pas disponibles en dehors de la portée (par rapport à la déclaration de fonction).
Alors, qu'est-ce que l'instruction de fonction?
L'instruction de fonction est parfois une autre façon de déclaration de fonction. Mais Kangax souligne qu'à Mozilla, l'instruction Fonction est une extension de la déclaration de fonction, permettant à l'instruction de déclaration de fonction d'être utilisée partout qui permet l'utilisation d'instructions. Cependant, l'instruction Fonction n'est pas la norme maintenant, il n'est donc pas recommandé d'être utilisé dans le développement de produits.
Commençons par quelques petits tests. Devinez ce qui apparaîtra dans les situations suivantes?
Question 1:
fonction foo () {function bar () {return 3; } return bar (); fonction bar () {return 8; }} alert (foo ());Question 2:
fonction foo () {var bar = function () {return 3; }; Bar de retour (); var bar = function () {return 8; };} alert (foo ());Question 3:
alert (foo ()); fonction foo () {var bar = function () {return 3; }; Bar de retour (); var bar = function () {return 8; };}Question 4:
fonction foo () {return bar (); var bar = function () {return 3; }; var bar = function () {return 8; };} alert (foo ());Si votre réponse n'est pas 8, 3, 3 et [Type Erreur: la barre n'est pas une fonction], alors continuez à lire ... (même si vous répondez correctement, vous devez continuer à lire)
Expliquons maintenant le test précédent.
La question 1 utilise la déclaration de fonction, ce qui signifie qu'ils sont hissés ...
Attendez, qu'est-ce que le hissage?
Voici une citation de Ben Cherry: "La déclaration de fonction et la variable de fonction sont généralement déplacées (« hissé ») vers le haut de la portée actuelle par l'interpréteur JavaScript».
Lorsque la déclaration de fonction est promue, l'ensemble du corps de fonction sera promu en conséquence, donc le code de la question 1 s'exécute comme celui-ci après avoir été expliqué par l'interprète:
// ** Séquence de traitement simulé pour la question 1 ** fonction foo () {// define bar une fois la fonction de fonction bar () {return 3; } // redéfinir la fonction informatique bar () {return 8; } // retourne sa barre de retour d'invocation (); // 8} alert (foo ());Cependant, on nous dit souvent que le code derrière l'instruction de retour ne peut pas fonctionner ...
Pendant l'exécution de JavaScript, il y a deux concepts: le contexte (ECMA 5 le décompose en lexicalenvironment, variable-environnement et cette binding) et processus (une série d'énoncés appelés en séquence). Lorsque le programme entre dans le domaine d'exécution, la déclaration provoque une variable-environnement. Ils sont différents de la déclaration (tels que le retour) et ne suivent pas les règles de fonctionnement des instructions.
L'expression de la fonction sera-t-elle promue?
Cela dépend de l'expression. Par exemple, la première expression de la question 2:
var bar = function () {return 3;};La (barre var) à gauche du signe égal est une déclaration variable. La déclaration variable sera promue, mais l'expression de l'affectation ne le sera pas. Ainsi, lorsque la barre est promue, l'interprète sera initialisé comme ceci: Var Bar = Undefined. La définition de la fonction elle-même ne sera pas promue.
(ECMA 5 12.2 Les variables avec InitialZier sont attribuées par affectation Expression lorsque la variable est exécutée, pas lorsque la variable est créée.)
Par conséquent, le code de la question 2 sera exécuté dans l'ordre suivant:
// ** Séquence de traitement simulé pour la question 2 ** fonction foo () {// Une déclaration pour chaque fonction d'expression de fonction var bar = non définie; var bar = non défini; // La première expression de fonction est exécutée bar = function () {return 3; }; // Fonction créée par la première fonction Expression est invoquée BAR (); // Deuxième fonction expression inaccessible} alert (foo ()); // 3Vous pouvez dire que cela peut être expliqué, mais la réponse à la question 3 est erronée. Je signalerai une erreur lors de l'exécution de Firebug.
Enregistrez le code dans un fichier HTML et essayez de l'exécuter sur Firefox. Ou exécutez dans IE8, Chrome ou safari. De toute évidence, la console Firebug ne favorisera pas la fonction lors de l'exécution du code dans la portée "globale" (en fait pas global, mais la portée "Firebug" unique - essayez simplement d'exécuter "cette fenêtre ==" dans la console Firebug).
La question 3 et la question 1 ont une logique similaire. Cette fois, la fonction FOO a été promue.
La question 4 est très simple, il n'y a aucune amélioration des fonctions du tout ...
On peut dire que, mais s'il n'y a aucune amélioration, la TypeError sera "Bar non définie" au lieu de "Bar pas une fonction". Il n'y a en effet aucune amélioration de la fonction dans cet exemple, mais il y a une amélioration variable. Par conséquent, la barre est déclarée au début, mais sa valeur n'est pas définie. Les autres codes sont exécutés dans l'ordre.
// ** Séquence de traitement simulé pour la question 4 ** fonction foo () {// Une déclaration pour chaque fonction expression de fonction var bar = undefined; var bar = non défini; Bar de retour (); // TypeError: "bar non défini" // aucune expression de fonction n'est atteinte} alert (foo ());À quoi d'autre devriez-vous faire attention?
L'officiel interdit l'utilisation de la déclaration de fonction dans les modules non fonctionnels (comme si). Cependant, tous les navigateurs le soutiennent, mais leurs explications sont différentes.
Par exemple, l'extrait de code suivant lancera une erreur dans Firefox 3.6 car il interprète la déclaration de fonction comme instruction de fonction (voir ci-dessus), donc x n'est pas défini. Mais dans IE8, Chrome 5 et Safari 5, la fonction X sera renvoyée (identique à la déclaration de fonction standard).
fonction foo () {if (false) {function x () {}; } return x;} alert (foo ());On peut voir que l'utilisation de la déclaration de fonction peut provoquer une confusion, alors a-t-il des avantages?
Vous pourriez dire que la déclaration de fonction est assez lâche - si vous essayez d'utiliser une fonction avant la déclaration, la promotion peut en effet corriger l'ordre afin que la fonction puisse être appelée correctement. Mais ce type de relâchement n'est pas propice à un codage rigoureux, et dans une perspective à long terme, il est susceptible de promouvoir plutôt que de prévenir les accidents. Après tout, il y a une raison pour laquelle les programmeurs organisent des instructions dans un ordre spécifique.
Y a-t-il donc d'autres raisons de soutenir l'expression de la fonction?
Qu'en penses-tu?
1) La déclaration de la fonction donne l'impression d'imiter les déclarations de méthodes de style Java, mais les méthodes Java ne sont pas les mêmes que JavaScript. Dans JavaScript, les fonctions sont des objets vivants avec des valeurs. Les méthodes Java ne sont que le stockage des métadonnées. Les deux pièces de code suivantes définissent la fonction, mais seule l'expression de la fonction ressemble à un objet est créé.
// Déclaration de fonction Add (a, b) {return a + b}; // function expressionvar add = function (a, b) {return a + b};2) L'expression de la fonction a plus d'utilisations. La déclaration de fonction ne peut exister que dans les orphelins comme une "déclaration". Tout ce qu'il peut faire est de créer une variable d'objet sous la portée actuelle. L'expression de la fonction, par définition, fait partie d'une grande structure. Si vous souhaitez créer des fonctions anonymes, ajoutez des fonctions aux prototypes ou utilisez des fonctions comme propriété d'autres objets, vous pouvez utiliser l'expression de la fonction. Chaque fois que vous utilisez des applications avancées, telles que Curry ou Compose, vous utilisez l'expression de la fonction lors de la création de nouvelles fonctions. L'expression de la fonction et la programmation fonctionnelle sont inséparables.
// fonction expressionvar sayshello = alert.curry ("Bonjour!");Y a-t-il des inconvénients dans l'expression de la fonction?
L'expression de la fonction crée la plupart des fonctions anonymes. Par exemple, la fonction suivante est anonyme, aujourd'hui n'est qu'une référence à une fonction anonyme:
var dès aujourd'hui = fonction () {return new Date ()}Est-ce que cela sera problématique? Pas dans la plupart des cas, mais comme l'a souligné Nick Fitzgerald, les fonctions anonymes de débogage peuvent être ennuyeuses. Il recommande d'utiliser des expressions de fonction nommées (NFES) comme espace de travail:
var aujourd'hui = fonction aujourd'hui () {return new Date ()}Cependant, comme Asen Bozhilov l'a dit (et la documentation de Kangax), les NFE ne peuvent pas être exécutés correctement ci-dessous IE9.
en conclusion
Une déclaration de fonction placée au hasard est des situations trompeuses et rarement (le cas échéant), et attribuer des valeurs aux variables avec l'expression de la fonction ne peut pas remplacer la déclaration de la fonction. Mais si une déclaration de fonction est requise, le mettre en haut de la portée peut réduire la confusion. Ne mettez jamais la déclaration de fonction dans une instruction IF.
Cela dit, la déclaration des fonctions peut être utile dans votre propre situation. Ce n'est rien. Le dogme du rôle est dangereux et fait souvent battre le code autour de la brousse. Plus important encore, vous comprenez le concept afin que vous puissiez décider quelle méthode créer la fonction en fonction de votre propre situation. Ce qui précède est l'intégralité du contenu de cet article. J'espère que cet article sera utile à tout le monde à cet égard.