Lorsqu'une fonction locale (interne) est déclarée en JavaScript, il y a deux options:
Déclaration avec le mot clé var
, affectation à la variable:
(function() {
var innerFunction1 = function() { ... };
innerFunction1();
}());
Déclarer uniquement avec le mot clé function
, sans affecter à la variable:
(function() {
function innerFunction2() { ... };
innerFunction2();
}());
Je peux voir un avantage du second: la fonction peut être déclarée sous le code qui l'appelle, il est donc plus facile de séparer les fonctions privées du code réellement exécuté.
Lequel est mieux et pourquoi?
En fait, il existe 3 façons de déclarer une fonction:
Déclaration de fonction : Une déclaration de fonction définit une variable de fonction nommée sans nécessiter d'attribution de variable. Les déclarations de fonctions se produisent en tant que constructions autonomes et ne peuvent pas être imbriquées dans des blocs non fonctionnels. ex: function innerFunction1 () { };
Expression de fonction: : Une expression de fonction définit une fonction comme faisant partie d'une syntaxe d'expression plus large (généralement une affectation de variable). Les fonctions définies via les expressions de fonction peuvent être nommées ou anonymes:
une. Utilisation d'une fonction anonyme - var innerFunction1 = function() { };
b. Utilisation d'une fonction nommée - var innerFunction1 = function myInnerFunction () { };
Constructeur de fonction : Un constructeur de fonction définit une fonction dynamiquement à l'aide du constructeur de fonction (). Notez que le corps de la fonction est passé à la fonction en tant qu'argument de chaîne. var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)
La troisième méthode n'est pas recommandée car le fait de passer le corps de la fonction sous forme de chaîne peut empêcher certaines optimisations du moteur JS et elle est sujette à des erreurs.
Les différences entre la déclaration de fonction et l'expression de fonction sont subtiles et vous devez choisir la méthode qui convient le mieux à vos besoins.
J'utilise l'expression de fonction là où j'ai besoin
Certaines différences entre une déclaration de fonction et une expression de fonction sont les suivantes:
Remarque: Une déclaration de fonction peut être facilement transformée en une expression de fonction en l'affectant à une var.
function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"
Plus de lecture:
Les deux notations sont fonctionnellement équivalentes.
Vous pouvez supposer que:
function a() {}
function b() {}
est interprété comme:
var a, b;
a = function a() {};
b = function b() {};
C'est pourquoi vous n'avez pas à déclarer pas à définir!) Avant utilisation. Vous pouvez réaffecter des fonctions après les avoir définies, comme vous le feriez avec une variable. Les fonctions sont hissées tout comme les variables, car ce sont des variables (esprit = soufflé? Bien!).
Déclarer avant utilisation
function a() { b(); } // using b before it's declared?
function b() {}
devient:
var a, b;
a = function a() { b(); }; // nope! b is declared, we're good
b = function b() {};
Redéfinir une fonction
function a() { alert("a"); }
a = function b() { alert("b"); }; // that's weird!
devient:
var a;
a = function a() { alert("a"); };
a = function b() { alert("b"); }; // oh, that looks normal
Déclarer vs définir
Déclarez: var x
. En anglais: "J'utiliserai la variable x
".
Définir est: x = 5
. En anglais "La variable x
a maintenant la valeur 5
".
La déclaration avant utilisation est requise et appliquée dans "use strict"
. La définition avant utilisation n'est pas requise. Si vos variables sont définies au moment de l'exécution, vous êtes bon.
Donc var x = 5
Est les deux une déclaration et une définition, tout comme function a() {}
.
Soyez prudent lorsque vous nommez des fonctions pour ne pas remplacer une variable existante:
var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"
--- (Lint les outils s'en occuperont.
Quand utiliser quelle notation?
Je recommanderais d'utiliser la notation d'expression de fonction (var a = function () {}
) uniquement lorsque vous aurez réaffecté la valeur de a
plus tard. L'expression de fonction signale ensuite au lecteur que a
va être réaffecté et que c'est intentionnel.
Un autre argument (mineur) pour la notation d'expression de fonction est un outil Lint comme JSLint qui peut vous obliger à déclarer (pas à définir!) Vos fonctions avant de les utiliser. Si vous avez des fonctions avec une définition récursive, c'est à dire. a
appelle b
et b
appelle a
, vous ne pouvez pas déclarer l'un avant l'autre en utilisant la notation de déclaration de fonction.
Modifier les notes: J'ai fait une légère révision sur les fonctions anonymes nommées. Il peut être utile de nommer des fonctions anonymes lorsque vous regardez une trace de pile. La fonction nommée donnera plus de contexte de peur qu'elle ne soit enregistrée comme 'anonyme'.
La différence est que la fonction avec VAR
est définie à au moment de l'exécution,
tandis que la fonction () sans VAR est définie à parse-time pour un bloc de script.
C'est la seule différence majeure ..
Ainsi, l'utilisateur décidera de la base de l'exigence, de l'utilisation et de l'adaptation à l'exigence.
Il n'y a aucune différence de sortie. Les deux peuvent toujours être appelés et les deux peuvent avoir leur prototype accédé par leur nom.
Il n'y a que deux différences réelles.
1) Lisibilité et préférence
Certaines personnes trouvent une façon plus facile à lire que d'autres et elles baseront à leur tour leur convention sur ce style. La convention suivante est importante.
2) Léger économiseur d'espace
La minification étant de plus en plus pertinente pour les scripts, vous pouvez voir comment il pourrait être avantageux d'utiliser la deuxième approche car elle ne nécessite pas l'utilisation de var
ou =
ce qui économisera 4 caractères d'espace insignifiants dans votre script minifié.
Résumé
Tout se résume à la préférence. Ce qui est mieux? À vous de me dire. Personnellement, j'utiliserai var
si j'ai l'intention d'en faire un objet avec new
, puis je capitaliserai la première lettre, telle que Person. Sinon, j'ai tendance à le camelCase et à omettre l'utilisation de var
.
D'accord avec @MarmiK. La différence entre deux méthodes est également la portée. Alors que la déclaration de fonction affecte la portée locale par défaut, la portée de la fonction affectée à une variable dépend de la portée de la variable.
var a;
(function() {
var innerFunction1 = function() { ... };//local scope
a=innerFunction1;//assigning to a global variable
}());
est accessible à l'échelle mondiale. Allez avec la déclaration de fonction si vous n'avez pas besoin de changer la portée. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope
var a;
(function() {
function innerFunction1() { ... };//local scope
a=innerFunction1;//It works too(Don't know why it should though)
}());
Ainsi, comme l'a souligné @Frits, il ne semble y avoir aucun avantage de portée à utiliser un type par rapport à l'autre.
var
sans nom de fonction
Fonction nommée sans var
:
var
échouera si cette fonction est appelée avant même que la variable de fermeture soit déclarée. Donc, vous devez savoir ce que vous faites.Fonction nommée avec ou sans var
Fonction nommée et avec var
Les déclarations locales doivent toujours utiliser var.
Eh bien, je dirais que le premier est meilleur car c'est une portée locale et la mémoire pourrait être effacée après que le symbole ne soit plus utilisé.
Il existe également une note sur le guide de style google javascript indiquant que le deuxième formulaire ne fait pas partie de la norme, il ne doit donc pas être utilisé.
Déclarations de fonction dans les blocs
Ne faites pas cela:
if (x) {function foo () {}} Bien que la plupart des moteurs de script prennent en charge les déclarations de fonction dans les blocs, il ne fait pas partie d'ECMAScript (voir ECMA-262, articles 13 et 14). Les pires implémentations sont incompatibles entre elles et avec les futures propositions EcmaScript. ECMAScript autorise uniquement les déclarations de fonctions dans la liste d'instructions racine d'un script ou d'une fonction. Utilisez plutôt une variable initialisée avec une expression de fonction pour définir une fonction dans un bloc:
si (x) {
var foo = function () {}
}
Source http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml .
Comme mentionné par Vega, il existe 3 façons de définir une fonction:
Les constructeurs de fonctions ont besoin du corps de fonction comme une chaîne qui:
rend la syntaxe incroyablement difficile à écrire: besoin d'échapper aux caractères spéciaux et à une autre folie, voir ci-dessous
var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.
Elle peut être invoquée avant la déclaration de fonction elle-même, ce qui introduit en fait de la complexité:
Les expressions de fonction sont plus simples:
Danger: Comme mentionné dans la "Déclaration d'inconvénient de la fonction", cela peut entraîner de nombreux problèmes, voici plus de détails à ce sujet.
Il est très facile de convertir des déclarations de fonction en expressions de fonction.
"Une déclaration de fonction cesse d'être une lorsqu'elle: soit fait partie d'une expression n'est plus un" élément source "d'une fonction ou du script lui-même. Un" élément source "est une instruction non imbriquée dans le script ou une fonction corps " https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2
"Les instructions de fonction sont sujettes à un hissage. Cela signifie que peu importe où une fonction est placée, elle est déplacée en haut de l'étendue dans laquelle elle est définie. Cela assouplit l'exigence que les fonctions soient déclarées avant d'être utilisées, ce qui, je pense, à la négligence. Il interdit également l'utilisation d'instructions de fonction dans les instructions if. Il s'avère que la plupart des navigateurs autorisent les instructions de fonction dans les instructions if, mais leur interprétation doit varier. Cela crée des problèmes de portabilité. " - extrait du livre: Javascript The Good Parts
La syntaxe est la suivante:
var varName = function [name]([param] [, param] [..., param]) { /* function expression */
statements
}
Choses à noter sur [name]
(juste après "fonction" dans la syntaxe):
Puis en utilisant [name]
vous pouvez faire des choses étranges/drôles comme ci-dessous. Notez que je ne recommande pas de le faire si vous êtes nouveau dans les définitions de fonction.
var count = 0;
var varName = function funcName() { /* function expression */
console.log('count is: ' + count );
if(count<1){
count++;
funcName(); /* calls function funcName another time */
}
};
varName(); // invokes function funcName via variable varName
funcName(); // throws an error as funcName is not reachable
voir la démo en direct sur jsbin.com/gijamepesu/1/edit?js,console
Une implémentation et une utilisation typiques seraient comme ci-dessous.
var myCoolFunc = function ( username, firstName, lastName ) { /* function expression */
console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
}
myCoolFunc();
Autre chose à noter: les expressions de fonction peuvent être invoquées immédiatement, contrairement aux déclarations de fonction. Cette fonctionnalité est utilisée dans IIFE, en savoir plus sur Quel est le but de placer des fichiers Javascript entiers dans des fonctions anonymes comme "(function () {…}) ()"?
Je pense que tous ceux qui commencent à programmer en JavaScript se posent tôt ou tard la question. Je reformulerais votre question pour:
Dois-je utiliser (je préfère utiliser) déclaration de fonction ( déclaration de fonction) ou expression de fonction ( var version)?
Dans la plupart des cas, on peut écrire du bon code JavaScript en utilisant un seul des constructions. Il est clair qu'il existe des différences importantes dans la sémantique, mais je tiens à souligner que, à mon avis, la réponse à la question est principalement la réponse concernant le style du programme . Je répondrais donc que dans les cas les plus réels le choix est la matière du goût .
Les personnes qui préfèrent utiliser instruction de fonction l'utilisent surtout pas alors qu'elles ont besoin de définir une variable de fonction en lecture seule et pas pourquoi elles ne veulent pas la déclarer avant qu'elle ne soit utilisée. À mon avis, on l'utilise donc surtout parce qu'on aime le formulaire.
Je pense donc qu'il n'y a pas objectivement réponse correcte à votre question. Le choix est subjectif. J'écris donc dans ma réponse quelle construction je préfère personnellement et dans quelles situations.
Mes premiers langages étaient Pascal, C, Fortran, C++ etc. J'utilisais maintenant C #. Donc quand j'ai commencé à écrire des programmes JavaScript, j'ai utilisé au début mon style existant d'écriture de programmes dans d'autres langues. Plus tard, j'ai changé le style de mon code JavaScript correspondant aux spécificités de la langue.
Je personnellement préfère utiliser le style expression et je déclare toutes les fonctions dans la première instruction de la fonction externe. Je trouve que le formulaire est généralement clair pour la sémantique JavaScript où le nom de la fonction est variable contient une valeur de fonction. Le nom de la fonction est soumis à hissage comme toute autre variable. Par exemple, mon code ressemble à ci-dessous
(function() {
"use strict";
var myFunc1 = function (x) {
// body where I can use x and this
alert("x=" + x + ", this.foo=" + this.foo);
},
localVar1 = {foo: "bar"};
myFunc1.call(localVar1, 1);
}());
J'utilise instruction de fonction très rarement et seulement si je déclare le constructeur de la classe comme:
(function() {
"use strict";
function MyClass(x) {
// the code of constructor
this.abc = x;
}
var myInstance = new MyClass("xyz");
alert(myInstance.abc);
}());
J'essaye de ne jamais utiliser le troisième formulaire:
(function() {
"use strict";
var myFunc1 = function myFunc2(x) {
...
};
...
}());
où myFunc2
sont déclarés en plus de myFunc1
. La mise en œuvre d'un tel formulaire dépend du navigateur Web. Cela a probablement du sens en cas d'utilisation de fonctions récursives.
Zakas dit que "Tant que vous définissez toujours des fonctions avant leur utilisation, vous pouvez vous sentir libre d'utiliser des déclarations de fonction ou des expressions de fonction."
Cela signifie que si votre code sera changé demain par une autre personne que vous ne connaissez pas un jour, et que c'est un gros projet que le développeur ne trouve pas où la fonction est déclarée, vous devez utiliser la déclaration de fonction (je veux dire la fonction x () {} ), ou si vous déclarez d'abord les fonctions, vous pouvez utiliser des expressions.