2012-06-08 14 views
8

Supongamos que tengo una función:Cómo pasar "esto" a setInterval ventana

function a() { 
    this.b = 1; 
    this.set = setInterval(function() {console.log(this.b);}, 200); 
} 

Así que cuando a.set() se llama la función anónima se llamará. Pero esto no funcionará porque en ese momento cuando la función se desencadena apunta al objeto ventana. Además, no es una buena idea usar a.b, ya que puede haber varias instancias de a.

¿Cuál es una buena solución a este problema?

+0

por qué no usa 'apply' o' call' https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply – Deeptechtons

+0

@Deeptechtons - No creo 'apply' o 'call' sirve para este problema, pero ¿podría explicar lo que tenía en mente en una respuesta? – nnnnnn

+0

@nnnnnn La pregunta es definitivamente un candidato para "¿Cómo puedo cambiar el contexto dentro de la función" tipo de pregunta. Que se resuelve usando appy, o call. Pero podría ser excesivo para este caso. – Deeptechtons

Respuesta

16

tienda una referencia a this:

function a() { 
    var self = this; 
    self.b = 1; 
    self.set = setInterval(function() {console.log(self.b);}, 200); 
} 

La función anónima que se pasa a setInterval tiene acceso a cualquier variable que contiene en su alcance, es decir, las variables locales de function a(). La magia de los cierres de JS mantiene vivas estas variables incluso después de que se haya completado a(), y cada invocación de a() obtiene su propio cierre.

+0

Sí, he visto ejemplos como ese, pero eso es exactamente lo que me confunde. Supongamos que "a" termina antes de que se desencadene el evento a los 200 ms, la variable auto parece que debería destruirse en ese momento. Si no, ¿cuándo sería destruido? después de que se borre el intervalo? – NSF

+0

Como mencioné en mi respuesta, una función interna tiene acceso a variables en el alcance de su función contenedora _incluso después de que la función contenedora haya finalizado_. En este caso, 'setInterval' continúa manteniendo una referencia a la función interna para que pueda seguir llamándola incluso después de que' a() 'haya terminado; hasta que se borre el intervalo, la referencia permanecerá activa y las variables permanecerán activas. Tenga en cuenta que 'a()' terminará _definitely_ antes de que se active el intervalo (no importa cuán corto sea el intervalo) porque JS se ejecuta en un único hilo. Google "Cierres de JavaScript" para más información. – nnnnnn

+0

tiene sentido. Gracias. – NSF

2

Simplemente guarde su referencia this en alguna otra variable, que no sea anulada por el window -cance más adelante. Más tarde puede usar esa variable para hacer referencia al objeto con el que comenzó.

function a() { 
    this.b = 1; 
    var that = this; 
    this.set = setInterval(function() {console.log(that.b);}, 200); 
} 
0

En su caso, puede simplemente:

function a() { 
    var _this = this; 
    this.b = 1; 
    this.set = setInterval(function() { 
     console.log(_this.b); 
    }, 200); 
} 

Normalmente, también puede tener un método de ayuda a Function.prototype.bindsolución la referencia this.

4

Ésta sería la solución más limpia, ya que la mayoría de las veces que realmente quieren cambiar el presente contexto para el método consecutiva llama:

// store scope reference for our delegating method 
    var that = this; 
    setInterval(function() { 
     // this would be changed here because of method scope, 
     // but we still have a reference to that 
     OURMETHODNAME.call(that); 
    }, 200); 
3

Ya que tenemos ES6 ahora, creo que necesitamos otra respuesta aquí :

utilizar una función de flecha:

function a() { 
    this.b = 1; 
    this.set = setInterval(() => {console.log(this.b);}, 200); 
} 

funciones de flecha, frente a las funciones normales, no tienen un contexto this en su propio. Esto significa que tiene acceso al exterior this.

+1

¡ES6 ha reducido mi sintaxis a casi nada, una vez más! ¡Gracias! – HoldOffHunger