Déclaration de fonction comme var au lieu de fonction

28

De plus en plus, je vois des fonctions déclarées comme

var foo = function() {

    // things
};

Au lieu de la façon dont j'avais appris, comme

function foo() {

    // things
}

Quelle est la différence? Meilleure performance? Portée? Dois-je utiliser cette méthode?

Steve Robbins
la source
il convient de noter qu'en javascript, les fonctions sont des citoyens de première classe . Cela vous permet de transmettre un comportement comme des objets. Ceci est très utile pour les rappels et la délégation, entre autres.
Chris Bye
Portée . L'encapsulation de nom de variable "// choses" empêche essentiellement / espérons-le les collisions de noms des "// choses" qu'il encapsule, avec d'autres JavaScript (fichiers) inclus. Une autre façon de penser est que vous avez créé un espace de noms "foo".
radarbob

Réponses:

25

var foo = function() {} définit une variable qui fait référence à une fonction anonyme.

function foo() {}définit une fonction nommée foo.

L'un ou l'autre peut être passé par nom en tant que paramètres de fonction et l'un ou l'autre peut être instancié si l'utilisation prévue est pour la POO.

À la fin de la journée, celui que vous utilisez est largement dicté par votre cas d'utilisation spécifique (Javascript est amusant comme ça;)). Si vous finissez par utiliser le premier, je vous suggère fortement de nommer la fonction:

var foo = function MY_function() {}. Cette convention de dénomination aide votre pile d'appels du débogueur à ne pas être inutile.

Demian Brecht
la source
1
Vous avez une gaffe là-bas sur la fonction () MY ...
Erik Reppen
1
@Demian Brecht, et qu'en est-il de l'approche var foo = function foo () {...}?
shabunc
@shabunc: Qu'en est-il? Il figure dans le dernier paragraphe de ma réponse.
Demian Brecht
@Demian Brecht, non, en fait dans le dernier paragraphe la variable est appelée fooet la fonction est appeléeMY_function
shabunc
@shabunc: Le nom n'a pas d'importance. Ce qui compte, c'est la valeur de la pile d'appels. Par exemple, [NAMESPACE] _ [nom fn] est la convention utilisée par Mozilla. Le nom lui-même n'a pas d'importance tant que votre convention est cohérente tout au long de votre projet.
Demian Brecht
13

expression de fonction:

//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };

L'expression func dans ce cas est anonyme mais affectée à une var pour référence. Ceci est différent d'une instruction de fonction étiquetée des manières suivantes:

  • il ne peut pas être hissé (appelé avant qu'il ne soit défini)
  • new someFunction().constructor.name === 'someFunction';//false les instances n'obtiennent pas le nom var pour constructor.name car une référence à la fonction est affectée au var mais le var, pas la fonction, est lié au nom var

Dans une déclaration de fonction étiquetée:

//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
  • travaux de levage
  • new someFunction().constructor.name === 'someFunction'; //true le nom est directement lié à la fonction.

De manière générale, il n'y a pas vraiment de bonne raison de faire de l'expression à var, sauf si vous voulez que les appels échouent si les choses bougent ou si vous définissez / attribuez une méthode sur une seule ligne. En fait, je trouve que le levage est utile pour organiser les objets avec des définitions de fonctions et de méthodes internes en bas afin que je puisse obtenir le comportement réel de l'objet et faire des définitions de méthodes publiques sur une seule ligne (en attribuant simplement des fonctions à this.avec le même nom) tout en un endroit pour faciliter la référence. Vous devriez toujours essayer d'utiliser des instructions étiquetées pour les constructeurs, IMO, afin de pouvoir identifier le «type» d'un objet via son constructeur.

Erik Reppen
la source
8

Votre premier exemple est une expression tandis que le deuxième exemple est une déclaration . La définition de fonctions en tant qu'expressions permet une plus grande flexibilité dans l'endroit où la définition peut se produire, à quoi vous pouvez l'affecter, que vous pouvez la passer en tant que paramètre, etc.

Par exemple:

SomeThing('abc', function(a,b) {return a*b;});

contre...

function tmp(a,b) { 
    return a*b;
}

SomeThing('abc', tmp);

Des exemples plus complexes deviendraient évidemment compliqués sans la syntaxe d'expression de fonction.

Regardez /programming/111102/how-do-javascript-closures-work

gahooa
la source
4

La principale différence pratique est le levage. Par exemple:

foo(); // alerts 'hello'
function foo() {alert('hello');}

contre

foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}

En outre, il s'agit d'un comportement indéfini

function foo(){
  if (true) {
    function bar(){}
  }
  bar();
}

alors que c'est ok.

function foo(){
  if (true) {
    var bar = function(){}
  }
  bar();
}
Austin
la source
7
Il n'y a absolument rien de mal à définir une fonction à l'intérieur d'une fonction dans JS. Il n'y a pas beaucoup d'endroits où vous ne pouvez pas définir une fonction dans JS.
Erik Reppen
2
@ErikReppen Vous ne pouvez certainement pas utiliser une déclaration de fonction dans des blocs non fonctionnels (comme dans une instruction if). Je n'arrive pas à trouver où je lis, ils ne peuvent pas être utilisés dans une autre fonction.
Austin
@Austin Il n'y a rien de mal non plus à une définition de fonction dans une ifinstruction!
Tim
@Austin: Vous l'avez peut-être lu sur w3schools? ;)
Demian Brecht
2
@ErikReppen Les expressions de fonction peuvent être utilisées n'importe où. Les déclarations de fonction ne peuvent pas l'être. Voir stackoverflow.com/questions/10069204/…
Austin