Frage

Ich habe einige Probleme mit einfacher alten JavaScript (keine Frameworks) mein Objekts in einer Callback-Funktion in referenzieren.

function foo(id) {
    this.dom = document.getElementById(id);
    this.bar = 5;
    var self = this;
    this.dom.addEventListener("click", self.onclick, false);
}

foo.prototype = {
    onclick : function() {
        this.bar = 7;
    }
};

Wenn ich jetzt erstellen Sie ein neues Objekt (nach dem DOM geladen ist, mit einer Spannweite # test)

var x = new foo('test');

Die ‚dies‘ innerhalb der Onclick-Funktion zeigt auf die Spanne # Test und nicht die foo-Objekt.

Wie bekomme ich einen Verweis auf meine foo Objekt innerhalb der Onclick-Funktion?

War es hilfreich?

Lösung

(extrahiert eine Erklärung, die in den Kommentaren in andere Antwort versteckt wurde)

Das Problem liegt in der folgenden Zeile:

this.dom.addEventListener("click", self.onclick, false);

Hier, übergeben Sie ein Funktionsobjekt als Rückruf verwendet werden. Wenn der Ereignisauslöser, wird die Funktion aufgerufen, aber jetzt hat es keinen Zusammenhang mit einem Objekt (this).

Das Problem kann durch das Einwickeln der Funktion (mit seiner Objektreferenz) in einem Verschluss wie folgt gelöst werden:

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);

Da die Variable selbst zugewiesen wurde das , wenn der Verschluss erstellt wurde, wird die Verschlussfunktion den Wert der Selbst Variable erinnern, wenn es zu einem späteren Zeitpunkt genannt wird.

Eine andere Möglichkeit, dieses Problem zu lösen ist, um eine Nutzenfunktion zu machen (und vermeiden Variablen für die Bindung das verwenden):

function bind(scope, fn) {
    return function () {
        fn.apply(scope, arguments);
    };
}

Der aktualisierte Code würde dann wie folgt aussehen:

this.dom.addEventListener("click", bind(this, this.onclick), false);

Function.prototype.bind ist ein Teil von ECMAScript 5 und bietet die gleichen Funktionalität. So können Sie tun:

this.dom.addEventListener("click", this.onclick.bind(this), false);

Für Browser, die ES5 noch nicht unterstützen, bietet MDN die folgende Shim :

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 

Andere Tipps

this.dom.addEventListener("click", function(event) {
    self.onclick(event)
}, false);

Für die jQuery Benutzer Suche nach einer Lösung für dieses Problem, sollten Sie a href verwenden <= "http://api.jquery.com/jQuery.proxy/" rel = "noreferrer" > jQuery.proxy

Die Erklärung dafür ist, dass self.onclick bedeutet nicht, was Sie denken, es bedeutet, in JavaScript. Es bedeutet eigentlich die onclick Funktion im Prototyp des Objekts self (ohne in irgendeiner Weise Referenzierung self selbst).

JavaScript nur hat Funktionen und keine Delegierten wie C #, so ist es nicht möglich, eine Methode zu übergeben und das Objekt, um es als Rückruf angewandt werden sollte.

Die einzige Möglichkeit, ein Verfahren in einem Rückruf zu nennen, ist es in einer Callback-Funktion selbst zu nennen. Da JavaScript-Funktionen Verschlüsse sind, sie sind in der Lage, die Variablen im Gültigkeitsbereich deklariert für den Zugriff auf sie erstellt wurden.

var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);

Eine gute Erklärung des Problems (ich hatte Probleme Lösungen bisher beschriebenen Verständnis) ist verfügbar hier .

Ich schrieb dieses Plugin ...

Ich denke, es nützlich sein wird,

jquery.callback

ist dies einer der verwirrendsten Punkte von JS: die ‚this‘ Variable auf den meisten lokalen Objekt bedeutet ... aber Funktionen sind auch Objekte, so ‚dies‘ Punkte gibt. Es gibt andere subtile Punkte, aber ich weiß nicht mehr, sie alle.

ich in der Regel vermeiden, dies 'verwenden, definieren Sie nur eine lokale ‚me‘ Variable und verwenden, die statt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top