web-dev-qa-db-fra.com

Définir la fonction locale en JavaScript: utiliser var ou non?

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?

57
Pavel S.

En fait, il existe 3 façons de déclarer une fonction:

  1. 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 () { };

  2. 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 () { };

  3. 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

  1. ne fonction singleton , ou
  2. pour déterminer la fonction à utiliser par programme (en utilisant une expression de fonction nommée).

Certaines différences entre une déclaration de fonction et une expression de fonction sont les suivantes:

  1. Les expressions de fonction vous permettent d'assigner différentes fonctions à la même variable à différents points.
  2. Une fonction définie par une déclaration de fonction peut être utilisée avant la déclaration de fonction elle-même (ou essentiellement n'importe où dans la portée actuelle), tandis qu'une fonction définie par une expression de fonction ne peut être utilisée qu'après le point où elle est définie.

Cliquez ici pour lire la comparaison détaillée de la déclaration de fonction par rapport à l'expression de fonction par rapport au constructeur de fonction @MDN

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:

44

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'.

7
Halcyon

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.

4
MarmiK

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.

2
Travis J

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

MODIFIER:

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.

1
Binu Pandian
  • var sans nom de fonction

    • c'est mieux si vous maîtrisez vos déclarations de variables: surtout quand elles sont déclarées.


  • Fonction nommée sans var:

    • implique une déclaration de variable ainsi nommée au début de la portée actuelle et cela peut éviter certaines erreurs,
    • mais: déclarer une fonction de cette façon, utiliser une variable de fermeture déclarée avec 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

    • est bon pour la déclaration de classe,
    • et pour le profilage, par exemple, Chrome dev sera plus explicite si les fonctions ne sont pas anonymes: elles auront un nom explicite et vous saurez où se trouve la partie lente de votre code.


  • Fonction nommée et avec var

    • est le moyen d'avoir la fonction comme portée nommée sans avoir la variable déclarée comme fermeture
    • tout en gardant la maîtrise de l'ordre de déclaration des variables.
1
lib3d

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 .

1
cavila

Définition d'une fonction javascript

Comme mentionné par Vega, il existe 3 façons de définir une fonction:

  1. constructeur de fonction
  2. déclaration de fonction
  3. expression de fonction

Contre du constructeur de fonction:

Les constructeurs de fonctions ont besoin du corps de fonction comme une chaîne qui:

  • peut empêcher certaines optimisations du moteur JS
  • 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.

Inconvénient de la déclaration de fonction:

Elle peut être invoquée avant la déclaration de fonction elle-même, ce qui introduit en fait de la complexité:

Avantages de l'expression de la fonction:

Les expressions de fonction sont plus simples:

  • vous "savez juste" à quelle variable il est affecté
  • vous ne pouvez pas appeler/référencer la variable à laquelle la fonction est affectée avant sa définition, ce qui est un comportement cohérent avec le reste des définitions javascript

En savoir plus sur: Conversion de déclarations de fonction en expressions de fonction

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


En savoir plus sur les expressions de fonction

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):

  • Le nom de la fonction peut être omis , auquel cas la fonction devient connue comme une fonction anonyme .
  • "Un nom de fonction ne peut pas être modifié, tandis que la variable à laquelle la fonction est affectée peut être réaffectée."
  • "Le nom de la fonction ne peut être utilisé que dans le corps de la fonction." , vous pouvez utiliser cette fonction pour laisser la fonction s’appeler de manière récursive.

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 () {…}) ()"?


Ressources

0
Adrien Be

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) {
            ...
        };
    ...    
}());

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.

0
Oleg

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.

0
cenk ebret