2011-03-30 14 views
40

Sé que esta pregunta no tiene mucho sentido, pero déjame intentar aclarar un poco.¿Cómo transfiero este contexto a un controlador de eventos?

tengo una clase, llamada ScrollBanner, y se ve menos como sigue (un montón omitido por razones de brevedad):

function ScrollBanner() { 
    this.initialize = function(selector) { 
     $('span#banner1-nav').click(this._onClickNavigation); 
    } 

    this._onClickNavigation = function(event) { 
     this.restartTimer(); // this == span#banner1-nav element from this.initialize 
     //... 
    } 

    this.restartTimer() { 
     //... 
    } 
} 

Como se puede ver this.initialize establece un controlador de clic a esto. _onClickNavigation. Algunos pueden esperar el este dentro del controlador de eventos para hacer referencia a la instancia de ScrollBanner, pero lamentablemente no es así. Se refiere al elemento que trigerred el evento click, en este caso lapso # banner1-nav

¿Cuál sería la mejor manera de conseguir esto hacer referencia a la instancia de clase ScrollBanner?

Respuesta

73

La forma tradicional/viejo:

captura this en una variable:

this.initialize = function(selector) { 
    var that = this; 
    $('span#banner1-nav').click(function(event) { 
     that._onClickNavigation(event); 
    }); 
} 

También podría asignar a un this por ejemplo, la variable instance:

function ScrollBanner() { 
    var instance = this; 
    // ... 
} 

y se refieren a instance en lugar de this en todas las llamadas.

La idea general es almacenar this en una variable en un ámbito superior.


La forma ECMAScript5:

ECMAScript5 introduce una nueva propiedad de funciones: .bind(). MDC's documentation muestra una implementación para los navegadores que no lo admiten. Con él puede vincular un determinado contexto a una función:

this.initialize = function(selector) { 
    $('span#banner1-nav').click(this._onClickNavigation.bind(this)); 
} 

pero detrás de escena está haciendo lo mismo. La ventaja es que usted hace uso de la funcionalidad incorporada en el navegador que es compatible.

Tenga en cuenta que esto es diferente de apply o call. Ambos establecen el contexto y ejecutan la función, mientras que bind solo establece el contexto sin ejecutar la función.


La forma jQuery:

jQuery proporciona un método $.proxy() que está haciendo lo mismo:

$('span#banner1-nav').click($.proxy(this._onClickNavigation, this)); 
+0

Buena decisión, por lo general hacen un hábito de asignar un 'var = this' que en la parte superior de mis constructores por lo siempre tienes una referencia a eso. Luego use 'that' todo el tiempo para que no haya confusión (asumiendo que está haciendo referencia a eso, y no a otra cosa) – brad

+2

Esto es bastante útil, pero se siente bastante sucio. :) –

+0

@JoeZephyr: Así son las cosas;) Por favor, eche un vistazo a mi actualización también. –

1

Sé que esto es una vieja pregunta, pero he visto que en el comentarios, se menciona $ .proxy().Sí, cambia el contexto de un objeto pero no en un evento jQuery.

$('.selector').click($.proxy(function() { 
    console.log(this); /* this is set to .selector */ 
}, this)); 

$ .proxy() devuelve la función en el ámbito de aplicación que this reffered pero luego que la función se devuelve y utilizada por click() que entonces cambia el ámbito de aplicación a .selector elemento.

Lo he probado hace un minuto, pero si lo tengo mal, por favor, digo

+4

No estoy seguro de si esto era diferente en las versiones antiguas de jQuery, pero este ejemplo muestra que está equivocado: http://jsfiddle.net/mazztgc9/. –

Cuestiones relacionadas