JavaScript Fonctionne comme une variable


Exemple

Une déclaration de fonction normale ressemble à ceci:

function foo(){
}

Une fonction définie comme celle-ci est accessible de n'importe où dans son contexte par son nom. Mais parfois, il peut être utile de traiter des références de fonctions comme des références d'objet. Par exemple, vous pouvez affecter un objet à une variable en fonction d'un ensemble de conditions, puis récupérer ultérieurement une propriété de l'un ou l'autre objet:

var name = 'Cameron';
var spouse;

if ( name === 'Taylor' ) spouse = { name: 'Jordan' };
else if ( name === 'Cameron' ) spouse = { name: 'Casey' };

var spouseName = spouse.name;

En JavaScript, vous pouvez faire la même chose avec les fonctions:

// Example 1
var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = function(value){ /*...*/ };
else if ( hashAlgorithm === 'md5' ) hash = function(value){ /*...*/ };

hash('Fred');

Dans l'exemple ci-dessus, le hash est une variable normale. On lui attribue une référence à une fonction, après quoi la fonction à laquelle il fait référence peut être appelée à l'aide de parenthèses, tout comme une déclaration de fonction normale.

L'exemple ci-dessus fait référence à des fonctions anonymes ... fonctions qui n'ont pas de nom propre. Vous pouvez également utiliser des variables pour faire référence à des fonctions nommées. L'exemple ci-dessus pourrait être réécrit comme ceci:

// Example 2
var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = sha1Hash;
else if ( hashAlgorithm === 'md5' ) hash = md5Hash;

hash('Fred');

function md5Hash(value){
    // ...
}

function sha1Hash(value){
    // ...
}

Vous pouvez également affecter des références de fonction à partir des propriétés de l'objet:

// Example 3
var hashAlgorithms = {
    sha1: function(value) { /**/ },
    md5: function(value) { /**/ }
};

var hashAlgorithm = 'sha1';
var hash;

if ( hashAlgorithm === 'sha1' ) hash = hashAlgorithms.sha1;
else if ( hashAlgorithm === 'md5' ) hash = hashAlgorithms.md5;

hash('Fred');

Vous pouvez affecter la référence à une fonction détenue par une variable à une autre en omettant les parenthèses. Cela peut entraîner une erreur facile à réaliser: tenter d'attribuer la valeur de retour d'une fonction à une autre variable, mais affecter accidentellement la référence à la fonction.

// Example 4
var a = getValue;
var b = a; // b is now a reference to getValue.
var c = b(); // b is invoked, so c now holds the value returned by getValue (41)

function getValue(){
    return 41;
}

Une référence à une fonction est comme toute autre valeur. Comme vous l'avez vu, une référence peut être attribuée à une variable et la valeur de référence de cette variable peut être affectée ultérieurement à d'autres variables. Vous pouvez transmettre des références à des fonctions comme toute autre valeur, y compris transmettre une référence à une fonction en tant que valeur de retour d'une autre fonction. Par exemple:

// Example 5
// getHashingFunction returns a function, which is assigned
// to hash for later use:
var hash = getHashingFunction( 'sha1' );
// ...
hash('Fred');


// return the function corresponding to the given algorithmName
function getHashingFunction( algorithmName ){
    // return a reference to an anonymous function
    if (algorithmName === 'sha1') return function(value){ /**/ };
    // return a reference to a declared function
    else if (algorithmName === 'md5') return md5;
}

function md5Hash(value){
    // ...
}

Vous n'avez pas besoin d'affecter une référence de fonction à une variable pour l'invoquer. Cet exemple, basé sur l'exemple 5, appelle getHashingFunction, puis appelle immédiatement la fonction renvoyée et transmet sa valeur de retour à hashedValue.

// Example 6
var hashedValue = getHashingFunction( 'sha1' )( 'Fred' );

Une note sur le levage

Gardez à l'esprit que, contrairement aux déclarations de fonctions normales, les variables qui référencent des fonctions ne sont pas "hissées". Dans l'exemple 2, les fonctions md5Hash et sha1Hash sont définies au bas du script, mais sont disponibles partout immédiatement. Où que vous définissiez une fonction, l'interpréteur le "haut" de sa portée, le rendant immédiatement disponible. Ce n'est pas le cas pour les définitions de variables, donc le code comme celui-ci se brise:

var functionVariable;

hoistedFunction(); // works, because the function is "hoisted" to the top of its scope
functionVariable(); // error: undefined is not a function.

function hoistedFunction(){}
functionVariable = function(){};