2011-04-02 13 views
12

Vamos a considerar este fragmento de código JavaScript:setTimeout argumento de devolución de llamada

function Person(name) { 
    this.name = name; 
} 

Person.prototype.showName = function() { 
    alert(this.name); 
} 


var mike = new Person("mike"); 
//mike.showName(); 

window.name = "window"; 

No entiendo la diferencia entre el comportamiento de

setTimeout(mike.showName(), 5000); 

y

setTimeout(function(){ 
    mike.showName(); 
}, 5000); 

¿Por qué es el comportamiento ¿diferente? Realmente me confunde. Gracias.

+1

¿Qué diferencia de rendimiento está notando? –

+5

Estoy bastante seguro de que OP significa "comportamiento" cuando dice "rendimiento". –

Respuesta

45

Su pregunta realmente tiene nada en absoluto que ver consetTimeout. Simplemente necesita comprender la diferencia entre una llamada de función y una referencia a una función.

Considere estas cuatro tareas:

var one = function() { mike.showName(); }; 
var two = mike.showName; 
var three = mike.showName(); 
var four = (function() { mike.showName(); })(); 

Los dos primeros asignar una referencia a una función de sus respectivas variables. Las últimas dos, sin embargo, llaman a las funciones (para eso están los paréntesis) y asignan sus valores de retorno a los vars en el lado izquierdo.

cómo se relaciona con setTimeout:

La función setTimeout espera como primer argumento una referencia a una función, ya sea de manera one o two anterior sería correcto, pero three y four no lo haría. Sin embargo, es importante tener en cuenta que no es, en sentido estricto, un error para pasar el valor de retorno de una función a setTimeout, aunque con frecuencia verá eso.

Esto es perfectamente normal, por ejemplo:

function makeTimeoutFunc(param) { 
    return function() { 
     // does something with param 
    } 
} 

setTimeout(makeTimeoutFunc(), 5000); 

No tiene nada que ver con la forma en setTimeout recibe una función como argumento, pero que lo hace.

+1

muchas gracias hombre. Tu respuesta es genial. Sin embargo, todavía tengo una confusión. ¿Podría decirme por qué 'mike.showName()' se ejecutará primero mientras 'function() {mike.showName()' espera sus 5 segundos? Gracias de nuevo. – jsnewman

+3

@jsnewman - Pasando 'mike.showName()' dice ejecutar la función 'showName' en este momento y pasar lo que devuelve como la devolución de llamada que se ejecutará en 5 segundos (que no es nada). Sin embargo, pasar 'function() {mike.showName()}' proporciona 'setTimeout' con una función anónima para ejecutar cinco segundos a partir de ahora. Pasan cinco segundos y se ejecuta la función de envoltura externa. Contiene una línea, que es la llamada a 'showName', que se ejecuta en ese momento. –

8

No es un problema de rendimiento. Una de las formas en que se mostró simplemente no funciona (llama a la función de inmediato en lugar de cuando se agota el tiempo de espera).

setTimeout(mike.showName(), 5000); ejecutará la función showName y establece su valor de retorno como la devolución de llamada de tiempo de espera que no funcionará.

setTimeout(function(){ mike.showName(); }, 5000); crea una función anónima y establece esto como la devolución de llamada de tiempo de espera. Cuando el tiempo de espera se dispara, se llama a la función y llama a su función showName().

Fyi, setTimeout('mike.showName();', 5000); también funcionaría. Pero no hacen eso - es tan malo como usar eval(). Además de eso, hace que tu código sea menos legible ya que el código en la cadena no se puede resaltar con sintaxis.

+0

'setTimeout (mike.ShowName, 5000)' también funcionará –

+0

¿Podría decirme por qué 'mike.showName()' se ejecutará primero mientras 'function() {mike.showName()' espera su hora? Muchas gracias. – jsnewman

+0

Porque realmente llama a la función en esa línea. Si lo envuelve en una función anónima o simplemente pasa la función sin '()' no se llama, la función se pasa. – ThiefMaster

4

setTimeout(mike.showName(), 5000); ejecuta mike.showName() inmediatamente y pasa el valor devuelto a setTimeout()

setTimeout(function(){ mike.showName(); }, 5000); pasa un puntero a la función en su lugar. De esta manera, setTimeout puede ejecutar la función, en lugar de su valor de retorno.

12

Si la respuesta aceptada es demasiado largo para leer:

setTimeout(mike.showName(), 5000); 

Esto ejecutará cualquier mike.showName()vuelve después de 5000 milisegundos.

setTimeout(function(){ mike.showName(); }, 5000); 

Esto ejecutará función anónima después de 5000 milisegundos que llama mike.showName(), la función real.

Otra forma de conseguir mismo efecto:

setTimeout(mike.showName.bind(mike), 5000); 
+0

totalmente, de acuerdo, la respuesta aceptada no ayudará a los principiantes. – Pavel

+0

¡La mejor respuesta para lo que estaba buscando! –

Cuestiones relacionadas