详解Typescript里的This的使用方法_第1页
详解Typescript里的This的使用方法_第2页
详解Typescript里的This的使用方法_第3页
详解Typescript里的This的使用方法_第4页
详解Typescript里的This的使用方法_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、详解Typescript的ThiS勺使用方法目录-this参数&对象方法调用:普通函数调用,构造器调用:c和pp调用ThisTypesThisTypethis可以说是stipt难理解的特性之一了,Typescript的this似乎更加复杂了,Typescript的this有三中场景,不同的场景都有不同意思。-this参数限制调用函数时的this类型this类型用于支持链式调用,尤其支持c继承的链式调用ThisType用于构造复杂的ct0函数this参数由于S支持灵活的函数调用方式,不同的调用场景,this的指向也有所不同-作为对象的方法调用-作为普通函数调用*作为构造器调用作为ctiprt和y

2、pecctiprtt调用i对象方法调用这也是绝大部分this的使用场景,当函数作为对象的方法调用时,this指向该对象et类型striconstobj=name:yj,getName()retrthis可以自动推导为estriete类型stri这里有个坑就是如果对象定义时对象方法是使用箭头函数进行定义,则this指向的并不是对象而是全局的i,Typescrip也自动的帮我推导为icsteyeteretrthise报错fch这里的this指向的是iet运行e寸报错普通函数调用即使是通过非箭头函数定义的函数,当将其赋值给变量,并直接通过变量调用时,其运行时this执行的并非对象本身csteyete

3、retrthisecstete指向的是si,运行时报错很不幸,上述代码在编译期间并未检查出来,我们可以通过为et添加this的类型标注解决该问题name:stringinterce/限定getName调用时的this类型getName(this:Obj):stringconstobj:Obj=name:yj,getName(),obj.getName()/checkokconstfn1=obj.getNamefn1()/checkerror这样我们就能报保证调用时的this的类型安全构造器调用在class出现之前,一直是把function当做构造函数使用,当通过n

4、ew调用function时,构造器里的this就指向返回对象functionPeople(name:string)=name/checkerrorPtotype.getName=function()constpeople=newPeople()/checkerrorinterfacePeoplename:stringgetName():stringinterfacePeopleConstructornew(name:string):People/声明可以作为构造函数调用prototype:People/声明prototype,支

5、持后续修改prototypeconstctor=(function(this:People,name:string)=nameasunknown)asPeopleConstructor/类型不兼容,二次转型totype.getName=function()constpeople=newctor(yj)console.log(people:,people)console.log(people.getName()当然最简洁的方式,还是使用classclassPeoplename:stringconstructor(name:strin

6、g)=name/checkokgetName()constpeople=newPeople(yj)/checkok这里还有一个坑,即在class里publicfieldmethod和method有这本质的区别考虑如下三种methodclassTestname=1method1()method2=function()/checkerrormethod3=()=consttest=newTest()console.log(test.method1()/1cons

7、ole.log(test.method2()/1console.log(test.method3()/1虽然上述三个代码都能成功的输出1,但是有这本质的区别methodi:原型方法,动态this,异步回调场景下需要自己手动bindthismethod2:实例方法,类型报错,异步场景下需要手动bindthismethod3:实例方法,静态this,异步场景下不需要手动bindthis在我们编写React应用时,大量的使用了method3这种自动绑定this的方式,但实际上这种做法存在较大的问题-每个实例都会创建一个实例方法,造成了浪费-在处理继承时,会导致违反直觉的现象classParentco

8、nstructor()this.setup()setup=()=console.log(parent)classChildextendsParentconstructor()super()setup=()=console.log(child)constchild=newChild()/parentclassParent2constructor()this.setup()setup()console.log(parent)classChild2extendsParent2constructor()super()setup()console.log(child)constchild2=newChi

9、ld2()/child在处理继承的时候,如果superclass调用了示例方法而非原型方法,那么是无法在subclass里进行override的,这与其他语言处理继承的override的行为向左,很容出问题。因此更加合理的方式应该是不要使用实例方法,但是如何处理this的绑定问题呢。目前较为合理的方式要么手动bind,或者使用decorator来做bindimportautobindfromautobind-decoratorclassTestname=1autobindmethod1()call和apply调用call和apply调用没有什么本质区别,主要区别就

10、是ae的传递方式,不分别讨论。和普通的函数调用相比,call调用可以动态的改变传入的his幸运的是Typesci借助hi参数也支持对call调用的类型检查interfacePeoplename:stringconstobj1=name:yj,getName(this:People)constobj2=name:zrj,constobj3=name2:zrj,obj1.getName.call(obj2)obj1.getName.call(obj3)/checkerror另外call的实现也非常有意思,可以简单研究下其实现我们的实现就叫做call首先需要确定call

11、里第一个参数的类型,很明显第一个参数的类型对应的是函数里的数类型hi参数的类型,我们可以通过ThisaaeeHy具来获取一个函数的hi参interfacePename:strinoplefunctionctor(this:People)typeThisArg=ThisParameterType为ypep类型ThisParametertypeThisParamTextends(t的实现也很简单,借助ie即可eeterType=Textends(this:unhis:inferU,.args:any)=ay.argsayay但是我们怎么获取当前函数的类型呢,通过泛型实例化和泛型约束interfac

12、eCallableFunctioncall2(this:(this:T)=any,thisArg:T):anyinterfacePeoplename:stringfunctionctor(this:People)ctor.call2()/在进行c调用时,根据allale(的定义其hi参数类型为hisT而此时的hi即为c而根据c的类型定义,其类型为hiseple)实例化即可得此时的T实例化类型为eple即his的类型为eple进一步的添加返回值和其余参数类型eaceallalecicallTeesayhishisTahisT.args:ThisTypes为了支持需要支持方法的返回类型由调用示例确

13、定,这实际上需要类型系统的额外至此。考虑如下代码classeturnthiseturnthisssexteeturnthiseturnthisstb=neonsta=newA()不报错报错ypeM1=ReturnTypetypeypeM2=ReturnTypevoid&ThisTypeletp:Point=x:10,y:20,moveBy(dx,dy)this/message:string,如果对象字面量进行了类型标注,且类型标注里指明了this类型,则使用该标注类型typePoint=x:numbery:numbermoveBy(this:message:string,dx:number,d

14、y:number):voidletp:Point=x:10,y:20,moveBy(dx,dy)this/message:string,将规则按从高到低排列如下*如果方法里显示标注了this类型,这是用该标注类型如果上述没标注,但是对象标注的类型里的方法类型标注了this类型,则使用该this类型如果上述都没标注,但对象标注的类型里包含了ThisType,那么this类型为T-如果上述都没标注,this类型为对象的标注类型-如果上述都没标注,this类型为对象字面量类型这里的一条重要规则就是在没有其他类型标注的情况下,如果对象标注的类型里如果包含了ThisType,那么this类型为T,这意味

15、着我们可以通过类型计算为我们的对象字面量添加字面量里没存在的属性,这对于Vue极其重要。我们来看一下Vue的apiimportVuefromvue;exportconstComponent=Vue.extend(data()returnmsg:hellomethods:greet()returnthis.msg+world;)这里的一个主要问题是greet是methods的方法,其this默认是methods这个对象字面量的类型,因此无法从中区获取data的类型,所以主要难题是如何在methods.greet里类型安全的访问到data里的msg。借助于泛型推导和ThisType可以很轻松的实现

16、,下面让我们自己实现一些这个apitypeObjectDescriptor=data:()=Dmethods:M&ThisTypedeclarefunctionextend(obj:ObjectDescriptor):D&Mconstx=extend(data()returnmsg:hello,methods:greet()returnthis.msg+world/check,)其推导规则如下首先根据对象字面量的类型和泛型约束对比可得到类型参数T和M的实例化类型结果D:msg:stringM:greet():todo接着推导ObjectDescriptor类型为data():msg:string,methods:greet():string&ThisType接着借助推导出来的ObjectDescriptor推导出greet里的this类型为msg:string&greet():todo因此推导出this.msg类型为string,进一步推导出greet的类型为string,至此所有类型推完。另外为了减小Typescript的类型推倒难度,应该尽可能的显示的标注类型,防止出现循环推导或者造成推导复杂度变高等导致编译速度过慢甚至出现死循环或者内存耗尽的问题。typeObjectDescriptor

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论