Steuern des Werts von 'this' in einem jQuery-Ereignis


74

Ich habe mit jQuery ein 'Steuerelement' erstellt und jQuery.extend verwendet, um es so OO wie möglich zu machen.

Während der Initialisierung meiner Steuerung verkabele ich verschiedene Klickereignisse wie diese

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

Beachten Sie, dass ich 'this' als Datenargument in der bind-Methode verwende. Ich mache das, damit ich auf Daten zugreifen kann, die an die Steuerinstanz angehängt sind, und nicht auf das Element, das das Klickereignis auslöst.

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

Nachdem ich in der Vergangenheit Prototype verwendet habe, erinnere ich mich an eine Bindungssyntax, mit der Sie steuern konnten, wie hoch der Wert von 'this' im Ereignis war.

Was ist der jQuery-Weg?


Keine Ahnung, warum Sie versuchen, jQuery OO zu machen, da jQuery funktionaler ist als OO.
Cletus

Antworten:


104

Sie können jQuery.proxy()mit anonymen Funktionen verwenden, nur ein wenig umständlich, dass "Kontext" der zweite Parameter ist.

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

39

Ich mag deinen Weg, benutze tatsächlich eine ähnliche Konstruktion:

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

und die erste Zeile von this.onClick:

var self = event.data.self;

Ich mag diesen Weg, weil dann sowohl das angeklickte Element (als dies) als auch das "this" -Objekt als Selbst angezeigt werden, ohne dass Verschlüsse verwendet werden müssen.


Das ist in der Tat sehr nützlich, der beste Ansatz, den ich bisher gesehen habe. Danke, Alter!
Eugene Kuzmenko

Ordentliche Lösung. Ich liebe es.
Gad D Lord

Du bist schlau wie ich :-D
Peterchaula

Das ist das beste. Kein zusätzlicher komplizierter Schließungscode. Danke
Kannan J

33

jQuery hat die jQuery.proxyMethode (verfügbar seit 1.4).

Beispiel:

var Foo = {
  name: "foo",

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

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

21

Ich glaube nicht, dass jQuery eine integrierte Funktion dafür hat. Sie können jedoch ein Hilfskonstrukt wie das folgende verwenden:

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 mit createDelegate () dynamische 'Wrapper-Funktionen' erstellen, die die Methode mit einem bestimmten Objekt als 'this'-Bereich aufrufen.

Beispiel:

function foo() {
    alert(this);
}

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

40
Leute, dieser Beitrag wurde im Februar 2009 geschrieben, zu diesem Zeitpunkt gab es noch keinen jQuery.proxy()(erschien in v.1.4, Januar 2010). Keine Notwendigkeit, abzustimmen.
Ferdinand Beyer

5
Geht es nicht darum, den besten Antworten die meisten Stimmen zu geben? Ich freue mich, wenn veraltete Antworten abgelehnt oder entfernt werden. Es hilft meiner Meinung nach, Fehlleitungen zu vermeiden.
Ben

1
Natürlich sollte die beste Antwort die meisten Stimmen erhalten, 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?
Ferdinand Beyer

1
Ich behaupte keineswegs, dass Sie etwas falsch gemacht haben. IMHO wird dieses Szenario von den Mechanismen von SO (zumindest AFAIK) einfach nicht gut abgedeckt. Antworten, die zu einem bestimmten Zeitpunkt sehr gut geeignet waren, wurden positiv bewertet und bleiben dort, auch wenn sie sich im Laufe der Zeit ungeeignet entwickeln, da andere Methoden entwickelt wurden, die die alten Mechanismen übertreffen. IMHO wäre es am besten, wenn es möglich wäre, diese Antworten so zu kennzeichnen, dass entweder der Autor benachrichtigt wird und möglicherweise reagiert oder ein Hinweis darauf gegeben wird, dass die Antwort möglicherweise veraltet ist.
Ben

4
@ben: Antworten sind möglicherweise veraltet, aber das ist kein Grund, dem Autor die Gutschrift zu entziehen, die er verdient hat, als die Antworten relevant waren. Ich denke, es ist besser, eine Flaggenfunktion für veraltete Antworten vorzuschlagen, als die einst richtige Antwort herunterzustimmen.
Mike Purcell

5

HTML 5-kompatible Browser bieten eine Bindemethode, bei Function.prototypeder es sich wahrscheinlich um die sauberste Syntax handelt und die nicht vom Framework abhängig ist, obwohl sie erst in IE 9 in den IE integriert wird. (Es gibt jedoch eine Polyfüllung für Browser ohne diese.)

Anhand Ihres Beispiels können Sie es folgendermaßen verwenden:

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

(Randnotiz: Die erste bindin dieser Anweisung ist Teil von jQuery und hat nichts damit zu tun. Function.prototype.bind)

Oder um etwas prägnanteres und aktuelleres jQuery zu verwenden (und Verwirrung durch zwei verschiedene Arten von binds zu vermeiden):

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

4

Sie können die Javascript- Bindemethode wie folgt verwenden:

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

var object = {coolValue: "bla"};


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

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

1
@LukeH Bindemethode ist nur ein js Code .. developer.mozilla.org/en-US/docs/JavaScript/Reference/…
Orlando

1
@JLRishe können Sie diese Polyfüllung für IE8
Orlando

@Orlando Du bist in der Tat richtig. Ich werde jetzt meinen früheren Kommentar löschen.
JLRishe

2

jQuery unterstützt keine Bindungen und die bevorzugte Methode ist die Verwendung von Funktionen.

Da in Javascript this.availableCategoryClick nicht bedeutet, dass die Funktion availableCategoryClick für dieses Objekt aufgerufen wird, empfiehlt jQuery, diese bevorzugte Syntax zu verwenden:

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

OO-Konzepte in Javascript sind schwer zu verstehen, funktionale Programmierung ist oft einfacher und besser lesbar.


1

Wenn man sieht, dass Funktionen den Umfang ändern, ist es am gebräuchlichsten, dies von Hand mit so etwas zu tun var self = this.

var self = this

$('.some_selector').each(function(){
  // refer to 'self' here
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.