JS中的this指向
在JS代码中,对于this我们只需要关注它的指向,确保返回的是一个正确的值。this的指向由下面这几点决定:
- 对象调用某函数,其中的this就指向该对象
- 通过apply、bind、call来显示指定函数的this
- new一个函数,函数中的this指向返回的实例化对象
- 箭头函数的this指向父级作用域的this
TS中的this指向和this类型
但是在TS代码中,我们要使用this,还需要确认this的类型
下面我们看一个代码
你知道getOption中的this指向谁吗?答案应该是不知道,因为非箭头函数的this指向,只在调用时才能确定,静态编译期是确定不了的。const option = {x: 1,y: 2,methods: {getOption: function ():number[] {return [this.x, this.y];},},};
而在TS中,不仅要关心this的指向,还要关心this的类型。如果在编辑器中写上面的代码,编译器会报类型警告:
图中所示,TS将this推断为含有
getOption属性的对象,这不是我们想要的
我们想要的是,this代表option对象,通过this可以访问x、y。这里我们需要显示地定义this的类型。
应该怎么做呢
用interface定义this的类型
可以在形参的位置定义this的类型
interface I_Option {x: number;y: number;getOption: () => [number, number];}const option = {x: 1,y: 2,methods: {getOption: function (this: I_Option) {return [this.x, this.y];},},};
这里先定义了一个接口I_Option,其中的结构和option相同。之后,在getOption的形参中,对this的类型做了定义。现在不会报类型警告了
当然这个只是类型的推断,this的真正指向还要看代码运行阶段。
上面是解决定义this类型定义的一个方法,还有一种方法,我们可以用TS内置函数ThisType<Type>来实现
用ThisType实现对this类型的定义
定义一个通用的对象类型
const obj = {data: {},methods:{}}
对象中的属性,无非就两种:数据,方法。所以上面的结构中,把数据全部放在了data里面,把方法全部放在了methods里面。
定义这样一个通用类型的对象,无非就是之后的接口类型定义能够方便一点
定义通用对象的接口类型
interface I_configObject<D,M>{data: D;methods: M}
接口接收两个泛型,第一个泛型作为data的类型,第二个泛型作为methods的类型
定义一个创建对象的函数
function createObj<D, M>(configObj: I_configObject<D, M>) {return {...configObj.data,methods: ...configObj.methods,};}
解释:
- 函数接收具有通用结构的configObj
- createObj也接受两个泛型,这两个泛型与data和methods的类型一致
- 你知道return中,为啥要这么做吗
使用createObj函数,看看效果
然后我们将符合通用类型的结构放进createObj函数中,就可以得到我们想要的option啦const option2 = createObj({data: {x: 1,y: 2,},methods: {getOption: function ():number[] {return [this.x, this.y];},},});
作者:额,心细的你是不是发现了什么?
读者:对,没有用ThisType啊,这连影子都没有见到。
作者:哦哦哦,对不起,立马加上如果你在编辑器中敲了上面的代码,发现还是会在this的地方报类型警告
interface I_configObject<D,M>{data: D;// 表示methods中的this是D & M类型的,// 所以在methods中,可以访问D中的属性(x,y)methods: M & ThisType<D & M>}
现在可以了,不会报类型警告了
下图中,可以看到TS推断出的this类型:
这正是我们想要的
其次,也可以放在 createObj的形参中
//表示configObj中的this指向是D & M类型的function createObj<D, M>(configObj: I_configObject<D, M> & ThisType<D & M>) {return {...configObj.data,methods: configObj.methods,};}
效果是一样的
ThisType
总结:
- JS中的this指向
- TS中,不仅关心this指向,还要关注this的类型
- 使用interface中,在形参中对this进行类型注释
- 使用ThisType
对this进行类型注释 - 用ThisType
做类型注释真是磨人
