web-dev-qa-db-fra.com

Qu'est-ce que cela signifie lorsqu'une variable est égale à une fonction?

Duplicata possible:
JavaScript: var functionName = function () {} vs function functionName () {}

En JavaScript, quel est le but de définir une variable comme une fonction? J'ai déjà vu cette convention et je ne la comprends pas complètement.

Par exemple, à un moment donné dans un script, une fonction est appelée comme ceci:

whatever();

Mais là où je m'attendrais à voir une fonction nommée whatever, comme ceci:

function whatever(){

}

Au lieu de cela, je verrai une variable appelée whatever définie comme une fonction, comme ceci:

var whatever = function(){

}

Quel est le but de cela? Pourquoi feriez-vous cela au lieu de simplement nommer la fonction?

39
daGUY

Remarque : Veuillez consulter la mise à jour à la fin de la réponse, les déclarations dans les blocs sont devenues valides (mais assez compliquées si vous n'utilisez pas le mode strict).


Voici une raison:

var whatever;

if (some_condition) {
    whatever = function() {
        // Do something
    };
}
else {
    whatever = function() {
        // Do something else
    };
}
whatever();

Vous pouvez voir du code comme celui-ci dans l'initialisation d'une bibliothèque qui doit gérer les différences d'implémentation (telles que les différences entre les navigateurs Web, le attachEvent d'A'la IE vs le addEventListener standard). Vous ne pouvez pas faire l'équivalent avec une déclaration de fonction:

if (some_condition) {
    function whatever() {    // <=== DON'T DO THIS
        // Do something
    }
}
else {
    function whatever() {    // <=== IT'S INVALID
        // Do something else
    }
}
whatever();

... ils ne sont pas spécifiés dans les structures de contrôle, donc les moteurs JavaScript sont autorisés à faire ce qu'ils veulent, et différents moteurs ont fait des choses différentes. (Edit: Encore une fois, voir la note ci-dessous, ils sont spécifiés maintenant.)

Séparément, il y a une grande différence entre

var whatever = function() {
    // ...
};

et

function whatever() {
    // ...
}

Le premier est un expression de fonction, et il est évalué lorsque le code atteint ce point dans l'exécution pas à pas du contexte (par exemple, la fonction dans laquelle il se trouve ou l'étape par étape). exécution du code global). Il en résulte également une fonction anonyme (la variable qui y fait référence a un nom, mais pas la fonction, ce qui a des implications pour aider vos outils à vous aider ) .

La seconde est une déclaration de fonction, et elle est évaluée lors de l'entrée dans le contexte, avant toute étape par étape le code est exécuté. (Certains appellent cela "hissage" parce que quelque chose plus bas dans la source se produit plus tôt que quelque chose plus haut dans la source.) La fonction reçoit également un nom propre.

Considérez donc:

function foo() {
    doSomething();
    doSomethingElse();
    console.log("typeof bar = " + typeof bar); // Logs "function"

    function bar() {
    }
}

tandis que

function foo() {
    doSomething();
    doSomethingElse();
    console.log("typeof bar = " + typeof bar); // Logs "undefined"

    var bar = function() {
    };
}

Dans le premier exemple, avec la déclaration, la déclaration est traitée avant le doSomething et tout autre code pas à pas est exécuté. Dans le deuxième exemple, parce que c'est une expression, il est exécuté dans le cadre du code pas à pas et donc la fonction n'est pas définie au-dessus (la variable est définie au-dessus, parce que var est également "hissé" ).

Et pour finir: pour le moment, vous ne pouvez pas faire cela dans le Web général côté client:

var bar = function foo() { // <=== Don't do this in client-side code for now
    // ...
};

Vous devriez être capable de faire cela, cela s'appelle expression de fonction nommée et c'est une expression de fonction qui donne à la fonction un nom propre. Mais divers moteurs JavaScript à différents moments se sont trompés, et IE a continué à se tromper en effet jusqu'à très récemment .


Mise à jour pour ES2015 +

Depuis ES2015 (alias "ES6"), les déclarations de fonction dans les blocs ont été ajoutées à la spécification.

Mode strict

En mode strict, le comportement nouvellement spécifié est simple et facile à comprendre: ils sont limités au bloc dans lequel ils se produisent et sont hissés en haut de celui-ci.

Donc ça:

"use strict";
if (Math.random() < 0.5) {
  foo();
  function foo() {
    console.log("low");
  }
} else {
  foo();
  function foo() {
    console.log("high");
  }
}
console.log(typeof foo); // undefined

(Notez comment les appels aux fonctions sont ci-dessus les fonctions dans les blocs.)

... est essentiellement équivalent à ceci:

"use strict";
if (Math.random() < 0.5) {
  let foo = function() {
    console.log("low");
  };
  foo();
} else {
  let foo = function() {
    console.log("high");
  };
  foo();
}
console.log(typeof foo); // undefined

Mode lâche

Le comportement en mode lâche est beaucoup plus complexe et de plus, en théorie, il varie entre les moteurs JavaScript dans les navigateurs Web et les moteurs JavaScript pas dans les navigateurs Web. Je ne vais pas entrer ici. Ne le fais pas. Si vous insistez sur les déclarations de fonction dans les blocs, utilisez le mode strict, où elles ont du sens et sont cohérentes dans tous les environnements.

35
T.J. Crowder

c'est pour que vous puissiez stocker des fonctions dans des variables et par exemple les passer à d'autres fonctions comme paramètres. Un exemple où cela est utile est d'écrire des fonctions asynchrones qui sont passées des rappels comme arguments

var callback = function() { console.log('done', result)}

var dosomething = function(callback) {
    //do some stuff here
    ...
    result = 1;
    callback(result);
}

Comme les fonctions sont des objets en javascript, vous pouvez également les étendre avec des propriétés et des méthodes.

2
joidegn

Les fonctions en JavaScript sont des objets; ils sont valeurs, en d'autres termes. Ainsi, vous pouvez toujours définir une variable pour faire référence à une fonction quelle que soit la façon dont la fonction est définie:

function foo() { ... }

var anotherFoo = foo;
anotherFoo(); // calls foo

Les fonctions sont des valeurs qui peuvent être utilisées comme propriétés d'objet, paramètres de fonction, éléments de tableau et tout ce qu'une valeur générale peut faire en JavaScript. Ce sont des objets et peuvent aussi avoir leurs propres propriétés.

1
Pointy

Lorsque vous affectez une fonction à une variable, vous pouvez ensuite la transmettre comme argument à d'autres fonctions, et également l'étendre pour utiliser le modèle d'objet Javascript.

1
lamplightdev

Si vous déclarez une fonction variable, en utilisant "var", au sein d'une fonction, la variable ne peut être accessible dans cette fonction. Lorsque vous quittez la fonction, la variable est détruite. Ces variables sont appelées variables locales. Vous pouvez avoir des variables locales portant le même nom dans différentes fonctions, car chacune n'est reconnue que par la fonction dans laquelle elle est déclarée.

0
Downpour046