共计 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);
这样就解决这个小问题啦~
正文完