在TypeScript中,类内方法的this类型默认是当前类的实例。然而,如果通过箭头函数定义方法,this的上下文将绑定到声明时,而不是调用时。
普通方法:
class Counter { value = 0; increment() { this.value++; } }
箭头函数:
class Counter { value = 0; increment = () => { this.value++; } }
细节:
class Foo { bar(this: Foo) { // ... } }
increment()和increment = () => {}在类中有什么区别?在用作回调时这对this的上下文有什么影响?
错误的回答:
正确的回答:
setTimeout(counter.increment, 0),则this将变为undefined(在严格模式下)或window(在非严格模式下),而箭头函数会保存其环境:class Demo { value = 1; inc() { console.log(this.value); } incArrow = () => { console.log(this.value); } } const d = new Demo(); setTimeout(d.inc, 0); // undefined或错误 setTimeout(d.incArrow, 0); // 1
故事
在一个使用响应式框架的项目中,类的方法直接作为回调传递,没有明确的bind。结果,this变为undefined,应用程序在访问this属性时崩溃。问题通过将方法重写为箭头函数或显式bind解决。
故事
开发者在方法中显式指定了this的类型,但忘记了在该方法中的箭头函数内部进行类型化。结果是,嵌套回调中的this指向的不是类的实例,而是window。团队面临状态泄漏问题,不得不重新设计事件架构。
故事
一个大型UI组件减慢了应用程序,因为所有方法都被定义为类的箭头字段(new Counter().increment = ...),这为每个实例创建了新的函数副本,而不是像普通方法那样在原型上定义一个副本。结果内存消耗增加,需要进行优化。