在实例方法中使用setInterval()遇到的陷阱

611次阅读
没有评论

共计 1007 个字符,预计需要花费 3 分钟才能阅读完成。

这几天有个需求,大致是需要网页监听手柄的操作,并绑上相应的事件。为了让这部分代码更便于维护,我写了一个类,这样只需要实例化一个类,然后设置好相应的事件函数就能直接用了,耦合性低。

在这个类中,有一个实例方法,能获取当前所有的手柄输入情况,存在实例属性 this.xx 中。还有一个实力方法,根据 this.xx 检测手柄输入的变化,一有操作,就执行设置好的函数。接下来,我使用 setInterval() 方法反复执行这两个方法,以达到“监听”的效果。

听上去很完美,可是实际运行下来,在实例方法内部的 this.xx 变量总是获取不到,经过一系列的排查,发现还是变量作用域的问题,请看如下例子:

class Person {constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    sayHello() {console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
    }
}

let john = new Person('John', 30);
setInterval(john.sayHello, 1000);

在这个例子中,有实例方法 sayHello(),方法内会获取实例属性 this.name 和 this.age。然后通过 setInterval()反复调用。然而,这个例子并不会正常输出内容,反而是:

Hello, my name is and I'm undefined years old.

原因是:如果在使用 setInterval 来调用 sayHello 方法,在回调函数内部,this 可能会指向全局对象(在浏览器中通常是 window 对象)而不是 john 的实例。解决方案也很简单,使用 bind 方法为方法绑定正确的上下文即可:

class Person {constructor(name, age) {
        this.name = name;
        this.age = age;
        this.sayHello = this.sayHello.bind(this); // 绑定方法的上下文
    }

    sayHello() {console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
    }
}

let john = new Person('John', 30);
setInterval(john.sayHello, 1000);

这样就解决这个小问题啦~

正文完
 
小唏
版权声明:本站原创文章,由 小唏 2023-10-19发表,共计1007字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码