JavaScript:当B继承自A时,A中的回调无法看到B.

时间:2010-12-10 22:03:58

标签: javascript callback scope this

无法弄清楚如何从父对象的回调中访问子对象的“扩展”属性。我的两次尝试都在下面。我希望函数“say_something”提醒“打个招呼”,其中“hi”来自孩子。相反,它说“说未定义”。

尝试1:我创建一个对象“a”,然后创建一个从它派生的新对象“b”。但是“a”中的回调(此处来自setTimeout)将无法访问正确的“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"

尝试2:常识说重新安排允许可以在回调中访问的“那个”变量。但与“this”不同,“that”无法访问“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,我使用Douglas Crockford的Object.create函数而不是(让我困惑)new()。它被复制到这里:

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

2 个答案:

答案 0 :(得分:2)

在setTimeout函数中,“this”始终引用Window对象。

我通常做的就是(测试和工作)

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

答案 1 :(得分:2)

如果你添加

a.say_something();

首先举例说明它也会返回say undefined。问题是setTimeout不会在调用它的范围内执行它调用的代码。

我们可以通过以下方式解决这个问题:

  1. 对现有对象alert('say ' + a.text);
  2. 的引用进行硬编码
  3. 使用call()apply()指定函数应执行的上下文。 (还有bind() - 对于最新的平台。)
  4. 方法#2是您正在寻找的。

    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!