2010-12-10 6 views
0

Kann nicht herausfinden, wie Zugriff auf die "erweiterten" Eigenschaften eines untergeordneten Objekts von einem Rückruf im übergeordneten Element erhalten. Meine zwei Versuche sind unten. Ich möchte für die Funktion "say_something" "say hi" alarmieren, wobei "hi" vom Kind kommt. Stattdessen heißt es "sag undefined".JavaScript: Wenn B von A erbt, können Callbacks in A B nicht sehen B

Versuch 1: Ich erstelle ein Objekt "a" und erstelle dann ein neues Objekt "b", das von ihm abgeleitet ist. Aber ein Callback in "a" (hier von einem setTimeout) hat keinen Zugriff auf das richtige "this".

var a = {}; 
a.say_something = function() { setTimeout(function() { alert("say " + this.text); }, 0); }; 

var b = Object.create(a); 
b.text = "hi"; 

b.say_something(); // alerts "say undefined" 

Versuch 2: Gemeinsame Weisheit sagt, neu ordnen für eine „die“ Variable zu ermöglichen, die in den Rückruf zugegriffen werden kann. Aber im Gegensatz zu "this", "dass" kein Zugriff auf Eigenschaften von "b":

var a = (function() { 
    var that = {}; 
    that.say_something = function() { setTimeout(function() { alert("say " + that.text); }, 0); }; 
    return that; 
}()); 

var b = (function() { 
    var that = Object.create(a); 
    that.text = "hi"; 
    return that; 
}()); 

b.say_something(); // alerts "say undefined" 

PS, verwende ich Douglas Crockford Object.create Funktion anstelle der (verwirrend für mich) neue(). Es wird hier kopiert:

if (typeof Object.create !== "function") { 
    Object.create = function (o) { 
     function F() {} 
     F.prototype = o; 
     return new F(); 
    }; 
} 

Antwort

2

Wenn Sie

a.say_something(); 

Ihnen wird es auch say undefined zurückkehren erstes Beispiel hinzufügen. Das Problem ist, dass setTimeout den aufgerufenen Code nicht in dem Bereich ausführt, in dem er aufgerufen wird.

Wir können dies entweder durch lösen:

  1. Hartcodierung einen Verweis auf das bestehende Objekt alert('say ' + a.text);
  2. Mit call() und apply() den Kontext fest, in dem sollte die Funktion auszuführen. (Und bind() auch -. Für die neuesten Plattformen)

Ansatz # 2 ist das, was Sie suchen.

var a = {}; 
a.text = "hello!"; 
function say_something() { 
    var that = this; // Save the reference to *this* this. 
    setTimeout(function() { console.log.call(that, "say " + that.text); }, 0); 
} 
a.say_something = say_something; 
a.say_something(); // say hello! 

var b = (function() { 
    var that = Object.create(a); 
    that.text = "hi there!"; 
    return that; 
}()); 

b.say_something(); // say hi there! 
+0

"Speichern Sie den Verweis auf * dies * dies" ist, was es getan hat. Vielen Dank! Um meinen Code "Versuch 2" zu erhalten, habe ich ein * zweites * "var that = this;" direkt vor dem Aufruf von setTimeout, wie Sie vorschlagen. (Es überschattet/überschreibt das erste "var that = {};", das ich woanders weiter verwende) –

2

In einer setTimeout-Funktion bezieht sich "this" immer auf das Window-Objekt.

Was ich in der Regel tun, ist so etwas wie (getestet und funktioniert)

a.say_something = function() { 
    var thisObj = this; 
    setTimeout(function() { 
     alert("say " + thisObj.text); 
    }, 0); 
}; 
+0

Wird das Eltern-Kind-Problem überhaupt angesprochen? –