开发者

JavaScript : when B inherits from A, callbacks in A cannot see B

开发者 https://www.devze.com 2023-01-30 04:55 出处:网络
Cannot figure out how to get access to the \"extended\" properties of a child object from a callback in the parent. My two attempts are below. I would like for the function \"say_something\" to alert

Cannot figure out how to get access to the "extended" properties of a child object from a callback in the parent. My two attempts are below. I would like for the function "say_something" to alert "say hi", where "hi" comes from the child. Instead, it says "say undefined".

Attempt 1 : I create an object "a", then create a new object "b" that derives from it. But a callback in "a" (here from a setTimeout) won't have access to the correct "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"

Attempt 2 : Common wisdom says re-arrange to allow for a "that" variable which can be accessed in the callback. But unlike "this", "that" cannot access properties from "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, I use Douglas Crockford's Object.create function instead of the (confusing to me) new(). It is copied here:

if ( typeof开发者_运维技巧 Object.create !== "function" ) {
    Object.create = function ( o ) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}


If you add

a.say_something();

to you first example it will also return say undefined. The problem is that setTimeout does not execute the code it calls in the scope in which it is called.

We can solve this by either:

  1. Hard-coding a reference to the existing object alert('say ' + a.text);
  2. Using call() and apply() to specify the context in which the function should execute. (And bind() too -- for the newest platforms.)

Approach #2 is what you are looking for.

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!


In a setTimeout function, "this" always refers to the Window object.

What I usually do is something like (tested and works)

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

精彩评论

暂无评论...
验证码 换一张
取 消