2010-09-04 19 views
19

Ora, io di solito richiama una funzione (che non richiede argomenti) con () come questo:Qual è il significato di "()" in una chiamata di funzione?

myFunction(); //there's empty parens 

Salvo jQuery chiamate dove posso farla franca:

$('#foo').bind('click', myFunction); //no parens 

fine. Ma di recente ho visto questo commento here su SO:

"Considerare l'utilizzo setTimeout(monitor, 100); invece di setTimeout('monitor()', 100); Eval è male :)".

Yikes! Siamo davvero eval() mettendo una stringa qui? Immagino di non capire veramente il significato e le implicazioni di "chiamare" una funzione. Quali sono le vere regole sulla chiamata e il riferimento alle funzioni?

risposta

44

Nelle funzioni JavaScript sono oggetti di prima classe. Ciò significa che puoi passare le funzioni come parametri a una funzione o trattarle come variabili in generale.

Diciamo che stiamo parlando di una funzione hello,

function hello() { 
    alert('yo'); 
} 

Quando abbiamo semplicemente scriviamo

hello 

ci riferiamo alla funzione che non esegue il suo contenuto. Ma quando si aggiungono le parentesi () dopo il nome della funzione,

hello() 

poi in realtà stiamo chiamando la funzione che avvisa "yo" sullo schermo.

Il metodo bind in jQuery accetta il tipo di evento (stringa) e una funzione come argomenti. Nel tuo esempio, stai passando il tipo - "clic" e la funzione reale come argomento.

Hai visto Inception? Considera questo esempio forzato che potrebbe rendere le cose più chiare. Poiché le funzioni sono oggetti di prima classe in JavaScript, possiamo passare e restituire una funzione dall'interno di una funzione. Creiamo quindi una funzione che restituisce una funzione quando viene invocato e la funzione restituita restituisce anche un'altra funzione quando viene richiamata.

function reality() { 
    return function() { 
     return function() { 
      alert('in a Limbo'); 
     } 
    }; 
} 

Qui reality è una funzione, reality() è una funzione, e reality()() è una funzione pure. Tuttavia, reality()()() non è una funzione, ma semplicemente undefined in quanto non restituiamo una funzione (non restituiamo nulla) dalla funzione più interna.

Quindi, per l'esempio di funzione reality, è possibile avere passato uno dei seguenti collegamenti a jQuery.

$('#foo').bind('click', reality); 
$('#foo').bind('click', reality()); 
$('#foo').bind('click', reality()()); 
+8

Stranamente, che ha fatto a chiarire le cose. –

+2

Yay, ora detengo il record per l'utilizzo della "funzione" il maggior numero di volte su tutte le risposte SO - 27. – Anurag

+3

+1 per riferimento Inception (e per una buona spiegazione, ovviamente) – delnan

3

non si sta facendo la stessa cosa nel tuo esempio jQuery come nel secondo setTimeout esempio - nel codice si passa la funzione e vincolante l'evento click.

Nel primo setTimout esempio, la funzione monitor viene passato e può essere richiamata direttamente, nel secondo, la puntura monitor() viene passato e deve essere eval ed.

Quando si passa una funzione in giro, si utilizza il nome della funzione. Quando lo si richiama, è necessario utilizzare lo ().

Eval invocherà ciò che è passato, quindi è necessario un () per una chiamata di funzione riuscita.

+0

Quindi il commento è sbagliato? Dovrebbe davvero passare 'setTimeout (monitor(), 100); // nota i paren'? –

+0

@Isaac Lubow: No, il codice è giusto - è solo che stai facendo qualcosa di diverso in ogni pezzo di codice. I due esempi non sono la stessa cosa. –

+0

Se si desidera eseguire il 'monitor' dopo 100 ms, si eseguirà' setTimeout (monitor(), 100); // noti i parens? –

7

L'esempio di jQuery bind è simile a setTimeout(monitor, 100);, si passa un riferimento di un oggetto funzione come argomento.

passaggio di una stringa ai metodi setTimeout/setInterval dovrebbe essere evitato per le stesse ragioni si dovrebbe evitare eval e il costruttore Function quando non è necessario.

Il codice passato come una stringa saranno valutati ed eseguire nel contesto di esecuzione globale, che può dare "questioni scope", si consideri il seguente esempio:

// a global function 
var f = function() { 
    alert('global'); 
}; 

(function() { 
    // a local function 
    var f = function() { 
    alert('local'); 
    }; 

    setTimeout('f()', 100); // will alert "global" 
    setTimeout(f, 100);  // will alert "local" 
})(); 

Il primo setTimeout chiamata nell'esempio di cui sopra , eseguirà la funzione globale f, poiché il codice valutato non ha accesso all'ambito lessicale locale della funzione anonima.

Se si passa il riferimento di un oggetto funzione al metodo setTimeout, come nella seconda chiamata setTimeout, verrà eseguita esattamente la stessa funzione che si fa riferimento nell'attuale ambito.

2

Prima di tutto, "()" non fa parte del nome della funzione. È la sintassi utilizzata per effettuare chiamate di funzione.

In primo luogo, si associa una funzione per un nome di identificatore o utilizzando una dichiarazione di funzione:

function x() { 
    return "blah"; 
} 

... o utilizzando un'espressione di funzione:

var x = function() { 
    return "blah"; 
}; 

Ora, ogni volta che vuoi per eseguire questa funzione, utilizzare i paren:

x(); 

La funzione setTimeout accetta entrambi e identificativo per una funzione o una stringa come primo argomento ...

setTimeout(x, 1000); 
setTimeout("x()", 1000); 

Se si fornisce un identificatore, allora verrà chiamato come una funzione. Se si fornisce una stringa, verrà valutata (eseguita).

Il primo metodo (la fornitura di un identificatore) è preferito ...

+0

'Se fornisci un identificatore, verrà richiamato come funzione. Se fornisci una stringa, allora verrà valutata (eseguita) .' Puoi spiegare la differenza? –

+0

@Isaac Se si fornisce una stringa, questa stringa verrà eseguita come codice JavaScript. Ad esempio: 'setTimeout ('x = 3;', 100)'. Come puoi vedere, nessuna funzione è chiamata qui. La stringa ''x = 3;'' viene valutata come espressione di assegnazione. D'altra parte, se si fornisce un nome identificatore, questo nome deve puntare a un oggetto funzione (che verrà quindi chiamato). –

+0

Gotcha. Grazie. –

Problemi correlati