2011-05-31 32 views
18

que tienen algún código javascript (dentro de un objeto):Javascript parámetro de la función anónima que pasa

toggle: function() { 
    var me = this; 
    var handler = function() { me.progress() }; 
    me.intervalId = setInterval(handler, me.intervalTime); 
    //...More code 
} 

Soy una especie de nuevo en Javascript, por lo que hacer lo anterior por lo que yo puedo decir en realidad pasa la variable me en anónimo la función. ¿Quería ver si hay una forma más declarativa de hacerlo? Quería algo en la línea de:

var handler = (function(o) { o.progress();})(this)); 

pero eso no parece estar funcionando ... ¿Me falta algo? ¿Es este un caso en el que "esta es la forma en que funciona el lenguaje, así que solo declara una variable local y ocúpate de ella"?

ACTUALIZACIÓN:

La fuente de mi problema era/es mi entendimiento claro del alcance y cierres en javascript. Encontré this article para ayudarme a entender un poco más.

+1

No funciona porque tiene '' demasiados. No 'var handler = (function (o) {o.progress();}) (this);' work maybe? – pimvdb

Respuesta

26

puede utilizar ".bind()":

var handler = function() { this.progress(); }.bind(this); 

Los nuevos navegadores tienen "bind()", y el Mozilla docs tener una implementación sólida se puede utilizar para reparar los navegadores antiguos.

+3

una solución aún más escueta para mi situación es 'var handler = this.progress.bind (this)'. ¡Gracias por tu contribución! – Jose

+0

Oh, bueno, por supuesto :-) Buen punto. – Pointy

1

Lo que tienes allí es un cierre. La función que se crea y asigna a handler mantiene una referencia al objeto me. Este es un JavaScript normal y cotidiano, y esa es la forma en que los cierres funcionan en general.

+1

Ese no es su problema. Él se queja de que el 'this' no puede ser cerrado, forzándolo a' var me = this'. – hugomg

+0

Estoy de acuerdo, pero lo que él quiere hacer equivale a luchar contra el idioma. A mí, y probablemente a todos los demás que escriben código JavaScript, me gustaría prescindir de la asignación de variables locales, pero es lo que es. –

5

La razón

var handler = (function(o) { o.progress();})(this)); 

no funciona, ya que sólo llama inmediatamente la función anon, por lo tanto, de inmediato llamando o.progress() y asigna el valor de retorno de la función anon (no definido) a handler. Es necesario devolver una función real de la función externa:

handler = (function(me){ 
    return function(){ 
     return me.progress(); 
    } 
}(this)); 

Por otro lado esto es equivalente e igual de mal aspecto tan mal aspecto como la asignación variable (pero todavía puede ser útil, sobre todo si esto necesita hacerse en un bucle, con el cambio i en lugar de lo arreglado esto).


Por cierto, si la función de progreso no tiene ningún llamadas a this dentro de él, simplemente haciendo handler = this.progress (sin las parens) podría ser suficiente.

0

¿Ha intentado devolver la función de esta manera?

var handler = function(o){ 
    return function(){ 
     o.progress(); 
    } 
}(me); 

Ahora se puede llamar:

handler(); 
5

La función anónima tiene acceso a me porque se ha declarado en el interior de la función externa (la función toggle); es cerrado por por la función externa.

Su función handler será llamada por setInterval, que pasa exactamente cero argumentos.Esto significa que no puede usar parámetros en la función del controlador mismo.

Te realmente quiero pasar me de forma explícita, se podría escribir una función de aceptar un parámetro, y tienen esa función devuelve una función anónima sin parámetros, pero que podría tener acceso a los parámetros de la función de creador:

toggle: function() { 
    var me = this; 
    var handler = (function (o) { return function() { o.progress() }; })(me); 
    me.intervalId = setInterval(handler, me.intervalTime); 
    //...More code 
} 

Pero esto básicamente agrega una capa de redirección sin realmente hacerlo más legible. A menos que saque esa función de creación de afuera:

function createProgressHandler(o) { 
    return function() { 
     o.progress(); 
    }; 
} 

// ... 

toggle: function() { 
    var me = this; 
    var handler = createProgressHandler(me); 
    me.intervalId = setInterval(handler, me.intervalTime); 
    //...More code 
} 
Cuestiones relacionadas