2015-08-21 11 views
5

Se chiamo una funzione denominata utilizzando setTimeout() e setInterval() senza le parentesi, funziona come previsto. Quando chiamo la stessa funzione con le parentesi, la esegue immediatamente o dà un errore.Chiamare una funzione quando si utilizza setTimeout() e setInterval() in JavaScript

Sto cercando una comprensione più approfondita in questa materia, quindi ciò che ho trovato sul web. Vorresti, ragazzi, spiegarmi perché è vero?

var func = function(){ 
    console.log("Bowties are cool."); 
} 

setTimeout(func(), 1500); 
// Prints "Bowties are cool." immediately 

setInterval(func(), 1500); 
// Throws an error 

setInterval(func, 1500); 
// Works as expected 

setTimeout(console.log("Bowties are cool."),1500); 
// This method has the same result as "setTimeout(func(), 1500)". 
+0

L'operatore '()' fa chiamare la funzione, così quando si usa 'func()' nella chiamata a 'setTimeout()' la funzione viene chiamata e il * risultato * (il valore di ritorno) viene passato per 'setTimeout()'. – Pointy

+0

Si suppone che si passi una funzione, non il risultato di una funzione (a meno che non restituisca una funzione) - quindi è sorprendente che non funzioni? –

+0

Le funzioni sono cittadini di prima classe in javascript. Puoi passare in giro come qualsiasi altra variabile. Quando si utilizza solo il nome di una funzione, si passa un riferimento alla funzione. Quando usi parentesi '()' stai chiamando la funzione e passa il * risultato * di quella chiamata. –

risposta

3

È necessario passare una funzione di riferimento sia setTimeout() e setInterval(). Ciò significa che si passa un nome di funzione senza lo () dopo di esso o si passa una funzione anonima.

Quando si include l'() dopo il nome della funzione come in func(), si sta eseguendo la funzione immediatamente e poi passando il risultato ritorno alla setInterval() oa setTimeout(). A meno che la funzione stessa non restituisca un altro riferimento alla funzione, questo non farà mai ciò che vuoi. Questo è un errore molto comune per i programmatori Javascript (ho fatto lo stesso errore io stesso quando ho imparato la lingua).

Quindi, il codice corretto è:

setTimeout(func, 1500); 
setInterval(func, 1500); 

Se conoscete altre lingue che usano i puntatori, si può pensare al nome di una funzione con il () dopo che è come come un puntatore alla funzione e che è quale riferimento di funzione è in Javascript e questo è ciò che si passa a una funzione quando si desidera che sia in grado di eseguire alcune funzioni in un secondo momento, non immediatamente.


Quando si esegue questa operazione erroneamente:

setTimeout(func(), 1500); 
setInterval(func(), 1500); 

Si sta eseguendo il tuo func() immediatamente e poi passando il risultato ritorno alla setTimeout() e setInterval(). Dal momento che il func() non restituisce nulla, si sono essenzialmente facendo questo:

func(); 
setTimeout(undefined, 1500); 

che è ciò che si osserva accadendo, ma non quello che volete.


Inoltre, se si desidera eseguire una funzione specifica chiamata come console.log("Bowties are cool."), allora si può avvolgerlo in un'altra funzione come questa:

setTimeout(function() { 
    console.log("Bowties are cool.") 
}, 1500); 

Quindi, ancora una volta si passa un riferimento funzione per setTimeout() che può essere eseguito più tardi anziché eseguirlo immediatamente, il che è ciò che stavi facendo.

+0

Quale percorso di logica prende il motore javascript quando viene eseguito? Cosa vede prima e come o in quale ordine gli argomenti vengono inseriti nello stack? Spero che questa domanda abbia un senso. – sufuninja

+0

@sufuninja: Se hai un'altra domanda, fai un'altra domanda e spiega cosa intendi. –

+0

@sufuninja: ti ho fornito un esempio dell'equivalente ordine di esecuzione nella mia risposta. Quando metti 'func()' come argomento, questo viene valutato per primo e poi il risultato viene passato come argomento. – jfriend00

0

setTimeout e setInterval attendono una funzione riferimento da passare a loro. Non dovresti chiamare la funzione all'interno delle chiamate setTimeout e setInterval.

errato (non fare questo):

setTimeout(func(), 1500); 
setInterval(func(), 1500); 
setTimeout(console.log("Bowties are cool."), 1500); 
setInterval(console.log("Bowties are cool."), 1500); 

corretta:

setTimeout(func, 1500); 
setInterval(func, 1500); 
setTimeout(function() { 
    console.log("Bowties are cool."); 
}, 1500); 
setInterval(function() { 
    console.log("Bowties are cool."); 
}, 1500); 

Nota come ho avvolto il console.log in una funzione anonima al fine di utilizzarlo con setInterval e setTimeout. Non è stato possibile passare console.log alle funzioni setInterval e setTimeout, poiché è necessario il parametro "Bowties are cool.". Lo avvolge nella funzione anonima risolve questo problema.

0

Quando si aggiungono parentesi dopo una funzione definita, si chiama o si richiama effettivamente la funzione.

Ma quando si passa una funzione come parametro all'interno di un'altra funzione, non si desidera chiamare la funzione, si desidera semplicemente passare un riferimento a questa funzione come parametro, (e la funzione passata in, essere disponibile per essere chiamato quando necessario).

per ulteriori informazioni sulle funzioni di callback in generale, here.

+1

Grazie per il link. Ho letto questo articolo prima ma il concetto non è ancora stato inserito. – sufuninja

Problemi correlati