如何从`setInterval`调用函数?

时间:2017-03-09 17:21:48

标签: javascript

function Obj() {
    this.func1 = function() {
            this.func2();
        },
        this.func2 = function() {
            setInterval(function() {
                this.func2();
            }, 200);
        }
}

function main() {
    var obj = new Obj();
    obj.func1();
}
main();

我有以下例外:

this.func2(); ^ TypeError: this.func2 is not a function

at Timeout._onTimeout(C: \Users\ Admin\ Desktop\ CANVAS\ test.js: 15: 12)
at ontimeout(timers.js: 365: 14)
at tryOnTimeout(timers.js: 237: 5)
at Timer.listOnTimeout(timers.js: 207: 5)

为什么this.func2在没有setInterval的情况下通话时功能正常,而且在我从setInterval拨打电话时不是功能?

6 个答案:

答案 0 :(得分:0)

因为在你的情况下这并不是指Obj。该上下文已更改,这是指setInterval上下文。

取消var self = this;行,其中存储this以供日后使用。

这应该有效

function Obj() {



  this.func1 = function() {
    this.func2();

  },

  this.func2 = function() {

    setInterval(function(){
      self.func2();
    }, 200);

  }

}

function main() {
  var obj = new Obj();
  obj.func1();

}

main();

答案 1 :(得分:0)

也许你想做这样的事情:

function Obj() {

  this.func1 = function() {
    this.func2();

  },

  this.func2 = function() {

    setInterval(function(){
      this.func2();
    }.bind(this), 200);

  }

}

但是这很快就会导致溢出,因为你在每次执行时都会创建一个新的间隔。也许您想使用setTimeout

答案 2 :(得分:0)

您可以绑定 this

this.func2 = function() {
  setInterval(function() {
    this.func2();
  }.bind(this), 200);

}

DEMO

答案 3 :(得分:0)

问题是setTimeout内的上下文是顶层,而不是对象的上下文,因此this将指向window(在浏览器中)而非您的宾语。有几种方法可以解决这个问题。

最新版本是使用bind方法绑定函数的上下文。



function Obj() {
  this.func1 = function() {
    this.func2();
  },

  this.func2 = function() {
    console.log('hi');
    setTimeout(this.func2.bind(this), 1000);
  }
}

function main() {
  var obj = new Obj();
  obj.func1();
}

main();




请注意,我使用this.func2.bind(this)作为setTimeout的回调(对于setInterval也是如此,如果我将其保留下来,那么您的示例将非常垃圾)。这意味着无论在何处召唤,它的this始终都是您的对象。

稍微更老的方法是将其包装在自我调用函数中,并将其隔离到this设置为对象的范围。



function Obj() {
  this.func1 = function() {
    this.func2();
  },

  this.func2 = function() {
    console.log('hi');
    setTimeout((function(self){
      return function () {
        self.func2();
      }
    })(this), 1000);
  }
}

function main() {
  var obj = new Obj();
  obj.func1();
}

main();




这种方式更复杂,但基本上我只是将你原来在自this作为self的参数传递的自调用函数中包含的内容,然后我使用{{1在它内部。

答案 4 :(得分:0)

this未传递给您的setInterval回调,因为它始终在全局上下文中调用,就像您使用setTimeout时一样。

thisundefined(在'use strict'模式下)或window对象(在常规/宽松模式下)。您可以将额外的参数传递给setInterval,然后将这些参数传递给您的回调:

this.func2 = function() {
  setInterval(function(self) {
    self.func2()
  }, 200, this)
}

Demo Snippet

function Obj() {

  this.func1 = function() {
    this.func2()
  }

  this.func2 = function() {
    setInterval(function(self) {
      console.log(typeof self.func2) //=> 'function'
    }, 200, this)
  }

}

function main() {
  var obj = new Obj()
  obj.func1()
}

main()

答案 5 :(得分:0)

使用箭头功能:

        this.func2 = function() {
            setInterval(() => {   this.func2();    }, 200);
        }