2009-02-06 15 views
71

He creado un 'control' usando jQuery y he usado jQuery.extend para ayudar a que sea lo más OO posible.Controlar el valor de 'esto' en un evento de jQuery

Durante la inicialización de mi control Me cable hasta varios eventos de clic al igual que

jQuery('#available input', 
      this.controlDiv).bind('click', this, this.availableCategoryClick); 

aviso de que estoy pasing 'esto' como el argumento de datos en el método de enlace. Lo hago para poder acceder a los datos adjuntos a la instancia de control en lugar del elemento que activa el evento de clic.

Esto funciona perfectamente, sin embargo sospecho que hay una mejor manera

Después de haber utilizado prototipo en el pasado, recuerdo una sintaxis de vinculación que permite controlar lo que el valor de 'esto' era en el evento.

¿Cuál es la forma de jQuery?

+0

No sé por qué estás tratando de hacer jQuery OO desde jQuery es más funcional que OO. – cletus

Respuesta

98

Usted puede utilizar jQuery.proxy() con función anónima, sólo un poco incómodo que el 'contexto' es el segundo parámetro.

$("#button").click($.proxy(function() { 
    //use original 'this' 
},this)); 
20

No creo que jQuery tenga una característica incorporada para eso. Sin embargo, se puede utilizar una construcción auxiliar como la siguiente:

Function.prototype.createDelegate = function(scope) { 
    var fn = this; 
    return function() { 
     // Forward to the original function using 'scope' as 'this'. 
     return fn.apply(scope, arguments); 
    } 
} 

// Then: 
$(...).bind(..., obj.method.createDelegate(obj)); 

De esta manera, se pueden crear funciones de contenedor '' dinámicas con CreateDelegate() que llama al método con un objeto dado como 'esto' ámbito de aplicación.

Ejemplo:

function foo() { 
    alert(this); 
} 

var myfoo = foo.createDelegate("foobar"); 
myfoo(); // calls foo() with this = "foobar" 
+39

Chicos, esta publicación fue escrita en febrero de 2009, en este momento no había 'jQuery.proxy()' aún (apareció en v.1.4, enero de 2010). No hay necesidad de downvote. –

+5

¿No se trata de dar la mejor respuesta con la mayor cantidad de votos? Aprecio si las respuestas obsoletas son rechazadas o eliminadas. Ayuda a evitar errores en mi humilde opinión. – ben

+1

Por supuesto, la mejor respuesta debería obtener la mayoría de los votos, como es el caso aquí. Pero esto no significa que las segundas mejores respuestas deberían ser rechazadas. Eso disminuye la reputación y simplemente no es justo. ¿Que esperas que yo haga? ¿Revisas y revisas mis antiguas respuestas de manera regular? –

2

jQuery no soporta une y la forma preferida es el uso de funciones.

Porque en Javascript, this.availableCategoryClick no significa llamar a la función availableCategoryClick en este objeto, jQuery aconseja para utilizar esta sintaxis preferida:

var self = this; 
jQuery('#available input', self.controlDiv).bind('click', function(event) 
{ 
    self.availableCategoryClick(event); 
}); 

conceptos orientados a objetos en Javascript son difíciles de entender, la programación es a menudo functionnal más fácil y más legible

1

Al ver que las funciones cambian el alcance, la forma más común es hacerlo a mano, con algo como var self = this.

var self = this 

$('.some_selector').each(function(){ 
    // refer to 'self' here 
} 
+0

convención dice que debe usar 'que' en su lugar .. – Orlando

36

me gusta su manera, de hecho, utilizar una construcción similar:

$('#available_input').bind('click', {self:this}, this.onClick); 

y la primera línea de this.onClick:

var self = event.data.self; 

me gusta esta manera porque entonces se obtiene tanto el elemento hizo clic (como este) como el objeto "este" como uno mismo sin tener que usar cierres.

+0

esto es de hecho muy útil, el mejor enfoque que he visto hasta ahora .. gracias amigo! –

+0

Solución limpia. Lo amo. –

+0

¡Gran idea, gracias! –

32

jQuery tiene el método jQuery.proxy (disponible desde la versión 1.4).

Ejemplo:

var Foo = { 
    name: "foo", 

    test: function() { 
    alert(this.name) 
    } 
} 

$("#test").click($.proxy(Foo.test, Foo)) 
// "foo" alerted 
4

puede utilizar el bind método de Javascript como esto:

var coolFunction = function(){ 
    // here whatever involving this 
    alert(this.coolValue); 
} 

var object = {coolValue: "bla"}; 


$("#bla").bind('click', coolFunction.bind(object)); 
+0

Desafortunadamente esto parece estar solo en JS 1.8.5, y esto corta navegadores como IE8. –

+1

@El método de enlace LukeH es solo un código js .. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – Orlando

+1

@JLRishe puede usar este [polyfill] (https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility) para IE8 – Orlando

4

HTML navegadores 5 conformes proporcionan una bind method en Function.prototype que es, probablemente, la sintaxis más limpia y no es marco dependiente, aunque no está integrado en IE hasta IE 9. (Sin embargo, existe un polyfill para navegadores sin él)

Según su ejemplo, puede usarlo así:

jQuery('#available input', 
     this.controlDiv).bind('click', this.availableCategoryClick.bind(this)); 

(nota: el primer bind en esta declaración es parte de jQuery y no tiene nada que ver con Function.prototype.bind)

O, para usar un poco más concisa y actualizada jQuery (y eliminar la confusión de dos tipos diferentes de bind s):

$('#available input', this.controlDiv).click(this.availableCategoryClick.bind(this)); 
Cuestiones relacionadas