2009-02-06 21 views
71

Ich habe ein 'Steuerelement' mit jQuery erstellt und jQuery.extend verwendet, um es so einfach wie möglich zu machen.Den Wert von 'this' in einem jQuery-Ereignis steuern

Während der Initialisierung meiner Kontrolle ich verschiedene Klick-Ereignisse wie so

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

Beachten Sie, dass ich pasing ‚this‘ als Daten Argument in der Methode bind verdrahten. Ich tue dies so, dass ich an Daten, die an die Steuerungsinstanz angehängt sind, eher von dem Element, das das Klickereignis auslöst, zugreifen kann.

Das funktioniert perfekt, aber ich vermute, dass es einen besseren Weg

verwendet Prototype in der Vergangenheit, ich bind Syntax erinnern, die Sie steuern dürfen, was den Wert von ‚this‘ in dem Fall war.

Was ist der jQuery Weg?

+0

Keine Ahnung, warum Sie versuchen, jQuery OO zu machen, da jQuery funktioneller als OO ist. – cletus

Antwort

98

Sie können jQuery.proxy() mit anonymer Funktion, verwenden Sie nur ein wenig umständlich, dass ‚Kontext‘ ist der zweite Parameter.

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

Ich glaube nicht, dass jQuery eine eingebaute Funktion dafür hat. Aber man könnte ein Helferkonstrukt wie folgt verwendet werden:

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

Auf diese Weise können Sie erstellen dynamische ‚Wrapper-Funktionen‘ mit CreateDelegate(), die das Verfahren mit einem bestimmten Objekt als ‚this‘ Anwendungsbereich nennen.

Beispiel:

function foo() { 
    alert(this); 
} 

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

Jungs, dieser Beitrag wurde in Februar 2009 geschrieben, zu diesem Zeitpunkt gab es keine 'jQuery.proxy()' noch (erschienen in v.1.4, Jan 2010). Kein Downvote nötig. –

+5

Geht es nicht darum, die besten Antworten zu geben? Ich schätze es, wenn veraltete Antworten abgelehnt oder entfernt werden. Es hilft, Irreführung IMHO zu vermeiden. – ben

+1

Natürlich sollte die beste Antwort die meisten Stimmen bekommen, wie es hier der Fall ist. Dies bedeutet jedoch nicht, dass die zweitbesten Antworten abgelehnt werden sollten. Das verringert den Ruf und ist einfach nicht fair. Was erwartest du von mir? Überprüfen und überarbeiten Sie meine alten Antworten regelmäßig? –

2

jQuery unterstützt nicht bindet und die bevorzugte Art und Weise ist es, Funktionen zu verwenden.

Weil in Javascript, this.availableCategoryClick bedeutet nicht, auf dieses Objekt die availableCategoryClick Funktion aufrufen, raten jQuery diese bevorzugte Syntax:

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

OO-Konzepte in Javascript sind schwer zu verstehen, functionnal Programmierung ist oft einfacher und lesbarer.

1

Wenn man sieht, dass Funktionen den Bereich ändern, ist es am üblichsten, dies von Hand zu tun, etwa mit var self = this.

var self = this 

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

Konvention besagt, dass Sie dass' stattdessen 'sollten .. – Orlando

36

ich dich mag in der Tat verwenden eine ähnliche Konstruktion:

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

und die erste Zeile des this.onClick:

var self = event.data.self; 

ich so mag, weil dann Sie bekommen Sowohl das Element als auch das Objekt "this" klickten als self, ohne dass Closures verwendet werden mussten.

+0

dies in der Tat sehr nützlich, ist der beste Ansatz, den ich bisher gesehen habe .. dank dude! –

+0

Saubere Lösung. Ich liebe es. –

+0

Tolle Idee, danke! –

32

jQuery hat die jQuery.proxy Methode (verfügbar seit 1.4).

Beispiel:

var Foo = { 
    name: "foo", 

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

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

Sie JavaScript bind Methode wie folgt verwenden:

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

var object = {coolValue: "bla"}; 


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

Leider scheint dies nur in JS 1.8.5 zu sein, und dies schneidet Browser wie IE8 aus. –

+1

@LukeH bind Methode ist nur einige js Code .. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – Orlando

+1

@JLRishe Sie diese verwenden können [polyfill] (https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility) für IE8 – Orlando

4

HTML 5-kompatiblen Browser bieten eine bind method auf Function.prototype das ist wahrscheinlich die sauberste Syntax und ist nicht gerüst abhängig, obwohl es ist bis IE 9 nicht in IE integriert. (Es gibt jedoch einen polyfill für Browser ohne.)

Basierend auf Ihrem Beispiel können Sie es wie folgt verwenden:

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

(Seite Anmerkung: die ersten bind in dieser Aussage ist ein Teil von jQuery und hat nichts mit Function.prototype.bind zu tun)

Oder etwas prägnanter zu bedienen und up-to-date jQuery (und beseitigt Verwirrung aus zwei verschiedene Arten von bind e):

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