-1
var i=0;
var t={
  a:function(){
    this.timer=setInterval(this.b,30);
  },
  b:function(){
    if(i++<1){
      console.log(this);
    }
  }
};
t.a();

为什么我得到了[圆形对象全局]?我想要'this'是指对象t

我怎么能得到那个?

我知道如何解决这个问题,下面的代码是正确的结果:

var i=0;
var t={
  a:function(){
    var that=this;
    this.timer=setInterval(function(){
      that.b();
    },30);
  },
  b:function(){
    if(i++<1){
      console.log(this);
    }
  }
};
t.a();
4

2 回答 2

2

您需要使用Function.prototype.bindFunction.prototype.call重新分配上下文,因为以这种方式调用的函数会将其上下文丢失到全局范围。在以下示例中最容易观察到这一点

o = { // an object
    foo: 1,
    bar: function () { // function assuming `this` is `o`
        return this.foo;
    }
};
f = o.bar; // function `f` loses scope of `o`
o.bar();   // 1,         o.foo is defined
f();       // undefined, window.foo is undefined

以下是您案例中的一些解决方案示例

// bind
function scopedInterval(func, delay, context) {
    return window.setInterval(func.bind(context), delay);
}
// or call
function scopedInterval(func, delay, context) {
    return window.setInterval(function () {func.call(context);}, delay);
}

在这些示例中,您将this作为第三个参数传递,即

this.timer = scopedInterval(this.b, 30, this);

如果你不这样做,上下文setIntervalwindow(我总是调用它,window.setInterval所以我不会忘记这一点)

于 2013-05-25T13:45:51.847 回答
0

正如 Crockford 在他令人惊叹的书中所说:“Javascripts: The Good Parts”:

当函数不是对象的属性时,它会作为函数调用[setInterval 就是这种情况]。当使用此模式调用函数时,“this”将绑定到全局对象。这是语言设计中的一个错误。如果语言设计正确,当调用内部函数时,“this”仍将绑定到外部函数的“this”变量。此错误的结果是方法不能使用内部函数来帮助它完成工作,因为内部函数不共享方法对对象的访问,因为它的“this”绑定到错误的值。[然后他谈到了与您发现的相同的解决方法]。,

您想知道为什么这不起作用是对的,对我来说,所有其他答案都无法正确解决这个问题。事实上,这是毫无意义的,正如 Crockford 所说,这是语言设计中的一个错误,可能会让人感到困惑。

于 2013-05-25T13:50:17.287 回答