2009-02-06 6 views
71

Ho creato un "controllo" utilizzando jQuery e utilizzato jQuery.extend per facilitare la sua realizzazione come OO possibile.Controllo del valore di "this" in un evento jQuery

Durante l'inizializzazione del mio controllo ho cablare vari eventi click in questo modo

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

Si noti che sto Pasing 'questo' come argomento i dati nel metodo bind. Lo faccio in modo che possa accedere ai dati collegati all'istanza di controllo piuttosto che all'elemento che attiva l'evento click.

Questo funziona perfettamente, ma ho il sospetto che ci sia un modo migliore

Avendo utilizzato Prototype in passato, mi ricordo una sintassi bind che vi ha permesso di controllare ciò che il valore di 'questo' era alla manifestazione.

Che cos'è il modo jQuery?

+0

Non so il motivo per cui si sta tentando di fare jQuery OO dal jQuery è più funzionale di OO. – cletus

risposta

98

È possibile utilizzare jQuery.proxy() con funzione anonima, solo un po 'imbarazzante che 'contesto' è il secondo parametro.

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

Non credo che jQuery abbia una funzione integrata per questo. Ma si potrebbe usare un aiutante costruire come il seguente:

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)); 

In questo modo, è possibile creare dinamiche 'funzioni wrapper' con createDelegate() che chiamare il metodo con un dato oggetto come il suo 'questo' ambito.

Esempio:

function foo() { 
    alert(this); 
} 

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

Ragazzi, questo post è stato scritto nel febbraio 2009, al momento non c'era ancora 'jQuery.proxy()' (apparso in v.1.4, gennaio 2010). Non c'è bisogno di downvotare. –

+5

Non si tratta di dare le migliori risposte al maggior numero di voti? Apprezzo se le risposte obsolete vengono sottovalutate o rimosse. Aiuta a evitare disguidi IMHO. – ben

+1

Ovviamente la migliore risposta dovrebbe ottenere la maggior parte dei voti, come è il caso qui. Ma questo non significa che le seconde migliori risposte dovrebbero essere sottovalutate. Ciò diminuisce la reputazione ed è semplicemente non giusto. Cosa ti aspetti che faccia? Controlla e rivedi le mie antiche risposte su base regolare? –

2

jQuery non supporta lega e il modo preferito è quello di utilizzare le funzioni.

Perché in Javascript, this.availableCategoryClick non significa chiamare la funzione availableCategoryClick su questo oggetto, jQuery consigliano di usare questa sintassi preferita:

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

concetti OO in Javascript sono difficili da capire, la programmazione functionnal è spesso più facile e più leggibile.

1

Vedendo che le funzioni cambiano ambito, il modo più comune è farlo a mano, con qualcosa come var self = this.

var self = this 

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

dice che dovresti usare 'that' invece .. – Orlando

36

Mi piace il tuo modo, infatti usare una costruzione simile:

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

e la prima linea di this.onClick:

var self = event.data.self; 

Mi piace questo modo perché poi si arriva sia l'elemento cliccato (come questo) sia l'oggetto "questo" come sé senza dover usare chiusure.

+0

questo è di fatto molto utile, l'approccio migliore che ho visto finora .. grazie amico! –

+0

Soluzione pulita. Lo adoro. –

+0

Ottima idea, grazie! –

32

jQuery ha il metodo jQuery.proxy (disponibile dal 1.4).

Esempio:

var Foo = { 
    name: "foo", 

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

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

è possibile utilizzare il bind metodo Javascript come questo:

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

var object = {coolValue: "bla"}; 


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

Purtroppo questo sembra essere solo in JS 1.8.5, e questo taglia i browser come IE8. –

+1

@LukeH bind method è solo un codice js .. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – Orlando

+1

@JLRishe è possibile utilizzare questo [polyfill] (https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility) per IE8 – Orlando

4

HTML browser 5-compliant forniscono un bind method su Function.prototype che è, probabilmente, la sintassi più pulito e non è framework-dipendente, anche se non è integrato in IE fino a IE 9. (C'è un polyfill per i browser senza, però.)

In base all'esempio, è possibile utilizzarlo in questo modo:

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

(nota a margine: il primo bind in questa informativa è parte di jQuery e non ha nulla a che fare con Function.prototype.bind)

O, per usare un po 'più conciso e up-to-date jQuery (e eliminare la confusione da due diversi tipi di bind s):

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