JavaScript Funziona come una variabile


Esempio

Una dichiarazione di funzione normale si presenta così:

function foo(){
}

Una funzione definita come questa è accessibile da qualsiasi parte all'interno del suo contesto dal suo nome. Ma a volte può essere utile trattare i riferimenti alle funzioni come i riferimenti agli oggetti. Ad esempio, è possibile assegnare un oggetto a una variabile in base ad alcune serie di condizioni e successivamente recuperare una proprietà dall'uno o dall'altro oggetto:

var name = 'Cameron';
var spouse;

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

var spouseName = spouse.name;

In JavaScript, puoi fare la stessa cosa con le funzioni:

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

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

hash('Fred');

Nell'esempio sopra, l' hash è una variabile normale. Viene assegnato un riferimento a una funzione, dopodiché la funzione a cui fa riferimento può essere invocata usando parentesi, proprio come una normale dichiarazione di funzione.

L'esempio sopra fa riferimento alle funzioni anonime ... funzioni che non hanno il loro nome. È anche possibile utilizzare le variabili per fare riferimento a funzioni con nome. L'esempio sopra potrebbe essere riscritto in questo modo:

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

Oppure, puoi assegnare i riferimenti alle funzioni dalle proprietà dell'oggetto:

// 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');

È possibile assegnare il riferimento a una funzione tenuta da una variabile a un'altra omettendo le parentesi. Ciò può comportare un errore facile da fare: tentare di assegnare il valore di ritorno di una funzione a un'altra variabile, ma assegnare casualmente il riferimento alla funzione.

// 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;
}

Un riferimento a una funzione è come qualsiasi altro valore. Come hai visto, un riferimento può essere assegnato a una variabile e il valore di riferimento di tale variabile può essere successivamente assegnato ad altre variabili. È possibile passare riferimenti a funzioni come qualsiasi altro valore, incluso il passaggio di un riferimento a una funzione come valore di ritorno di un'altra funzione. Per esempio:

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

Non è necessario assegnare un riferimento di funzione a una variabile per poterlo richiamare. Questo esempio, compilando l'esempio 5, chiamerà getHashingFunction e quindi richiamerà immediatamente la funzione restituita e passerà il suo valore di ritorno a hashedValue.

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

Una nota sul sollevamento

Tieni presente che, a differenza delle normali dichiarazioni di funzioni, le variabili che fanno riferimento alle funzioni non vengono "issate". Nell'esempio 2, le funzioni md5Hash e sha1Hash sono definite nella parte inferiore dello script, ma sono immediatamente disponibili ovunque. Indipendentemente da dove si definisce una funzione, l'interprete lo "issa" in cima alla sua portata, rendendolo immediatamente disponibile. Questo non è il caso delle definizioni di variabili, quindi il codice come il seguente si interromperà:

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