Javascript Inheritance and losing the context of &

2019-07-05 17:00发布

I am using John Resig's Simple JavaScript Inheritance and have run into an issue where I am losing what 'this' refers to. Using this code:

var Runner = Class.extend({ 
 init: function() {
  this.update();
  if(!this.interval) {
   this.interval = setInterval(this.update, this.period * 1000);
  }
 },
 stop: function() {
  clearInterval(this.interval);
 },
 update: function() {
  this.success()
 },
 success: function(){
 }
});

var SubRunner = Runner.extend({
 update: function() {
  this._super();
 },
 success: function(){
  alert('sub runner success');
 }
});

Running p = new SubRunner() works as I would expect and alerts sub runner success the first time. After the first run through it then tries to run the success function on the wrong 'this' (window).

I know Prototype gives you a bind function so that you can pass the context to the function but I haven't had any luck in doing something similar here. Does anyone have a starting point to figuring this out?

Thanks!

3条回答
干净又极端
2楼-- · 2019-07-05 17:15

When you pass this.update to setInterval you lose the context. The simplest solution is to do

var that = this;
this.interval = setInterval(function() { that.update() }, this.period * 1000);
查看更多
手持菜刀,她持情操
3楼-- · 2019-07-05 17:21
this.interval = setInterval(this.update, this.period * 1000);

When setTimeout calls a function it calls it in the global scope (it sets this to window).

You need to pass a function that calls this.update.

var self = this;
this.interval = setInterval(function(){
    self.update();
}, this.period * 1000);
查看更多
小情绪 Triste *
4楼-- · 2019-07-05 17:22

The problem is when you pass this.update to the setInterval function. In Javascript, the "this" depends on wether you call the function using dot notation, and functions will not remember where they came from if you pass them as callbacks or store them in a variable.

You can either add a wrapper function

var that = this;
setTimeout(function(){ that.update() }, this.perios*1000)

or you can use the bind method if its available in your browser (or you can use the similar function in Prototype).

setTimeout(this.update.bind(this), this.period*1000)
查看更多
登录 后发表回答