带有javascript范围的SetInterval

时间:2013-05-25 13:40:37

标签: javascript

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();

2 个答案:

答案 0 :(得分: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);

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

答案 1 :(得分:0)

正如克罗克福德在他惊人的书中所说:“Javascripts:The Good Parts”:

  

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

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