这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战
在 JavaScript 有关 this 问题,一直以来也是面试官喜欢问的一个问题,特别是 this 的指向问题,所以今天我们就聊一聊在 TypeScript 中类和方法中 this 指向问题。
重要的是要记住,TypeScript 并没有改变 JavaScript 的运行时行为,而 JavaScript 因为有一些独特的运行时行为。
class MyClass {
name = "MyClass";
getName() {
return this.name;
}
}
const c = new MyClass();
const obj = {
name: "obj",
getName: c.getName,
};
// Prints "obj", not "MyClass"
console.log(obj.getName());
长话短说,默认情况下,函数内this 具体表示什么值是取决于函数的调用方式。在这个例子中,因为函数是通过obj 引用调用的,所以 this值是obj而不是类实例。这很少是你希望发生的事情! TypeScript提供了一些方法来减轻或防止这种错误。
箭头函数
如何经常会遇到这种情况,调用函数时丢失了函数的 ·this 这个上下文对象,为了 this 丢失可以通过箭头函数来代替普通函数来解决这个问题。
call、apply和 bind方法不适合箭头函数,因为它们被设计为允许方法在不同的作用域内执行。因为箭头函数根据箭头函数定义的作用域来定义 this。
class MyClass {
name = "MyClass";
getName = () => {
return this.name;
}
}
const c = new MyClass();
const obj = {
name: "obj",
getName: c.getName,
};
// Prints "obj", not "MyClass"
console.log(obj.getName());
需要做一些权衡
- 即使在没有
TpyeScript对代码进行检测情况下,在运行时也需要保证this值保证正确地使用 - 这将占用更多的内存,因为类每一个实例都会拥有这种方式定义的方法的副本
- 无法在子类中使用
super.getName,因为在原型链中没有条目可以获取基类方法
在类中,一个叫做this的特殊类型动态地指向当前类的类型。接下来,下面的例子中可以看到modelType 类型为 Model3。
class Car{
model:string = ""
set(model:string){
this.model = model
return this
}
}
class Model3 extends Car{
clear(){
this.model = ""
}
}
const model_3 = new Model3()
const modelType = model_3.set("model 3") // Model3
this 也可以作为类方法的参数的类型使用
class Rect{
width:number;
height:number;
constructor(w:number,h:number){
this.width = w;
this.height = h;
}
compareWith(other:this){
}
}
这与写其他不同。Rect 的子类 Square 的 compareWith 方法现只接受的子类只是继承没否实现自己方法或定义自己的属性,例如length:number = 0 这是实例上调用 compareWith 方法就无法接受 Rect 的实例来作为参数
class Square extends Rect{
length:number = 0
}
const rect = new Rect(12,15)
const square = new Square(12,12)
console.log(square.compareWith(rect))