【问题标题】:setInterval calling class methodsetInterval 调用类方法
【发布时间】:2020-10-08 13:37:26
【问题描述】:

我无法让计时器调用我的类方法。这工作正常:

MyInput = class {
 constructor(params) {
  let input = params.input;
  input.addEventListener('focus', this.setTimer);
 }

 setTimer() {
  this.timer = window.setInterval(() => {
   console.log('yay');
  }, 300);
 }
};

但是这个:

MyInput = class {
 constructor(params) {
  let input = params.input;
  input.addEventListener('focus', this.setTimer);
 }

 setTimer() {
  this.timer = window.setInterval(this.lookupOptions, 300);
 }

 lookupOptions() {
  console.log('yay');
 }
};

不调用lookupOptions 方法,而是我在浏览器中的开发工具每 300 毫秒停止一次调试器(检查不同的值 - 始终与计时器同步)。过了一会儿,它打开了一些奇怪的文件VM[number],编号不同。我不知道为什么它不起作用。当我以同样的方式在课堂外使用计时器时,它工作正常,调用类方法似乎有些问题,但我无法弄清楚问题可能是什么。你能帮忙吗?

【问题讨论】:

  • window.setInterval(this.lookupOptions.bind(this), 300);
  • @enno.void Uncaught TypeError: Cannot read property 'bind' of undefined
  • 使用箭头函数将实例保留为上下文:input.addEventListener("focus", e => this.setTimer(e));this.timer = window.setInterval(() => this.lookupOptions(), 300);

标签: javascript class ecmascript-6 timer


【解决方案1】:

setInterval 调用该函数时,它会将this 的上下文更改为setInterval 的范围,即window 对象。

setInterval 中使用arrow function expression 包装回调。这可以防止范围被更改。

MyInput = class {
    constructor(params) {
        let input = params.input;
        input.addEventListener("focus", () => {
            this.setTimer();
        });
    }

    setTimer() {
        this.timer = window.setInterval(() => {
            this.lookupOptions();
        }, 300);
    }
  
    lookupOptions() {
         console.log("yay");
    }
}

或者使用每个函数对象上存在的.bind() 方法手动设置this 的范围。

MyInput = class {
    constructor(params) {
        let input = params.input;
        const boundSetTimer = this.setTimer.bind(this)
        input.addEventListener("focus", boundSetTimer);
    }

    setTimer() {
        const boundLookupOptions = this.lookupOptions.bind(this)
        this.timer = window.setInterval(boundLookupOptions, 300);
    }
  
    lookupOptions() {
         console.log("yay");
    }
}

或者使用实验性的public fields,它的作用与箭头函数表达式有些相同,但作为对象的方法。

MyInput = class {
    constructor(params) {
        let input = params.input;
        input.addEventListener("focus", this.setTimer);
    }

    setTimer = () => {
        this.timer = window.setInterval(this.lookupOptions, 300);
    }
  
    lookupOptions = () => {
         console.log("yay");
    }
}

【讨论】:

  • 不幸的是,绑定方法给了我“ncaught TypeError: Cannot read property 'bind' of undefined at HTMLInputElement.setTimer (clinput.js:44)”错误,而箭头方法“不是函数”错误。
  • 你还需要this.setTimer.bind(this)
  • 为什么input.addEventListener("focus", this.setTimer)在建筑工程中没有绑定?
  • 因为在构造函数中,this引用了实例,所以this.setTimer正确指向了方法。如果没有绑定,this inside setTimer 会指向输入。
  • @ChrisG 非常感谢您的解释!现在我明白它是如何工作的了。它正在工作!
猜你喜欢
  • 2020-07-31
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多