詳解Typescript里的This的使用方法_第1頁
詳解Typescript里的This的使用方法_第2頁
詳解Typescript里的This的使用方法_第3頁
詳解Typescript里的This的使用方法_第4頁
詳解Typescript里的This的使用方法_第5頁
已閱讀5頁,還剩3頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、詳解Typescript的ThiS勺使用方法目錄-this參數(shù)&對象方法調(diào)用:普通函數(shù)調(diào)用,構(gòu)造器調(diào)用:c和pp調(diào)用ThisTypesThisTypethis可以說是stipt難理解的特性之一了,Typescript的this似乎更加復(fù)雜了,Typescript的this有三中場景,不同的場景都有不同意思。-this參數(shù)限制調(diào)用函數(shù)時的this類型this類型用于支持鏈式調(diào)用,尤其支持c繼承的鏈式調(diào)用ThisType用于構(gòu)造復(fù)雜的ct0函數(shù)this參數(shù)由于S支持靈活的函數(shù)調(diào)用方式,不同的調(diào)用場景,this的指向也有所不同-作為對象的方法調(diào)用-作為普通函數(shù)調(diào)用*作為構(gòu)造器調(diào)用作為ctiprt和y

2、pecctiprtt調(diào)用i對象方法調(diào)用這也是絕大部分this的使用場景,當函數(shù)作為對象的方法調(diào)用時,this指向該對象et類型striconstobj=name:yj,getName()retrthis可以自動推導(dǎo)為estriete類型stri這里有個坑就是如果對象定義時對象方法是使用箭頭函數(shù)進行定義,則this指向的并不是對象而是全局的i,Typescrip也自動的幫我推導(dǎo)為icsteyeteretrthise報錯fch這里的this指向的是iet運行e寸報錯普通函數(shù)調(diào)用即使是通過非箭頭函數(shù)定義的函數(shù),當將其賦值給變量,并直接通過變量調(diào)用時,其運行時this執(zhí)行的并非對象本身csteyete

3、retrthisecstete指向的是si,運行時報錯很不幸,上述代碼在編譯期間并未檢查出來,我們可以通過為et添加this的類型標注解決該問題name:stringinterce/限定getName調(diào)用時的this類型getName(this:Obj):stringconstobj:Obj=name:yj,getName(),obj.getName()/checkokconstfn1=obj.getNamefn1()/checkerror這樣我們就能報保證調(diào)用時的this的類型安全構(gòu)造器調(diào)用在class出現(xiàn)之前,一直是把function當做構(gòu)造函數(shù)使用,當通過n

4、ew調(diào)用function時,構(gòu)造器里的this就指向返回對象functionPeople(name:string)=name/checkerrorPtotype.getName=function()constpeople=newPeople()/checkerrorinterfacePeoplename:stringgetName():stringinterfacePeopleConstructornew(name:string):People/聲明可以作為構(gòu)造函數(shù)調(diào)用prototype:People/聲明prototype,支

5、持后續(xù)修改prototypeconstctor=(function(this:People,name:string)=nameasunknown)asPeopleConstructor/類型不兼容,二次轉(zhuǎn)型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有這本質(zhì)的區(qū)別考慮如下三種methodclassTestname=1method1()method2=function()/checkerrormethod3=()=consttest=newTest()console.log(test.method1()/1cons

7、ole.log(test.method2()/1console.log(test.method3()/1雖然上述三個代碼都能成功的輸出1,但是有這本質(zhì)的區(qū)別methodi:原型方法,動態(tài)this,異步回調(diào)場景下需要自己手動bindthismethod2:實例方法,類型報錯,異步場景下需要手動bindthismethod3:實例方法,靜態(tài)this,異步場景下不需要手動bindthis在我們編寫React應(yīng)用時,大量的使用了method3這種自動綁定this的方式,但實際上這種做法存在較大的問題-每個實例都會創(chuàng)建一個實例方法,造成了浪費-在處理繼承時,會導(dǎo)致違反直覺的現(xiàn)象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調(diào)用了示例方法而非原型方法,那么是無法在subclass里進行override的,這與其他語言處理繼承的override的行為向左,很容出問題。因此更加合理的方式應(yīng)該是不要使用實例方法,但是如何處理this的綁定問題呢。目前較為合理的方式要么手動bind,或者使用decorator來做bindimportautobindfromautobind-decoratorclassTestname=1autobindmethod1()call和apply調(diào)用call和apply調(diào)用沒有什么本質(zhì)區(qū)別,主要區(qū)別就

10、是ae的傳遞方式,不分別討論。和普通的函數(shù)調(diào)用相比,call調(diào)用可以動態(tài)的改變傳入的his幸運的是Typesci借助hi參數(shù)也支持對call調(diào)用的類型檢查interfacePeoplename:stringconstobj1=name:yj,getName(this:People)constobj2=name:zrj,constobj3=name2:zrj,obj1.getName.call(obj2)obj1.getName.call(obj3)/checkerror另外call的實現(xiàn)也非常有意思,可以簡單研究下其實現(xiàn)我們的實現(xiàn)就叫做call首先需要確定call

11、里第一個參數(shù)的類型,很明顯第一個參數(shù)的類型對應(yīng)的是函數(shù)里的數(shù)類型hi參數(shù)的類型,我們可以通過ThisaaeeHy具來獲取一個函數(shù)的hi參interfacePename:strinoplefunctionctor(this:People)typeThisArg=ThisParameterType為ypep類型ThisParametertypeThisParamTextends(t的實現(xiàn)也很簡單,借助ie即可eeterType=Textends(this:unhis:inferU,.args:any)=ay.argsayay但是我們怎么獲取當前函數(shù)的類型呢,通過泛型實例化和泛型約束interfac

12、eCallableFunctioncall2(this:(this:T)=any,thisArg:T):anyinterfacePeoplename:stringfunctionctor(this:People)ctor.call2()/在進行c調(diào)用時,根據(jù)allale(的定義其hi參數(shù)類型為hisT而此時的hi即為c而根據(jù)c的類型定義,其類型為hiseple)實例化即可得此時的T實例化類型為eple即his的類型為eple進一步的添加返回值和其余參數(shù)類型eaceallalecicallTeesayhishisTahisT.args:ThisTypes為了支持需要支持方法的返回類型由調(diào)用示例確

13、定,這實際上需要類型系統(tǒng)的額外至此??紤]如下代碼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,將規(guī)則按從高到低排列如下*如果方法里顯示標注了this類型,這是用該標注類型如果上述沒標注,但是對象標注的類型里的方法類型標注了this類型,則使用該this類型如果上述都沒標注,但對象標注的類型里包含了ThisType,那么this類型為T-如果上述都沒標注,this類型為對象的標注類型-如果上述都沒標注,this類型為對象字面量類型這里的一條重要規(guī)則就是在沒有其他類型標注的情況下,如果對象標注的類型里如果包含了ThisType,那么this類型為T,這意味

15、著我們可以通過類型計算為我們的對象字面量添加字面量里沒存在的屬性,這對于Vue極其重要。我們來看一下Vue的apiimportVuefromvue;exportconstComponent=Vue.extend(data()returnmsg:hellomethods:greet()returnthis.msg+world;)這里的一個主要問題是greet是methods的方法,其this默認是methods這個對象字面量的類型,因此無法從中區(qū)獲取data的類型,所以主要難題是如何在methods.greet里類型安全的訪問到data里的msg。借助于泛型推導(dǎo)和ThisType可以很輕松的實現(xiàn)

16、,下面讓我們自己實現(xiàn)一些這個apitypeObjectDescriptor=data:()=Dmethods:M&ThisTypedeclarefunctionextend(obj:ObjectDescriptor):D&Mconstx=extend(data()returnmsg:hello,methods:greet()returnthis.msg+world/check,)其推導(dǎo)規(guī)則如下首先根據(jù)對象字面量的類型和泛型約束對比可得到類型參數(shù)T和M的實例化類型結(jié)果D:msg:stringM:greet():todo接著推導(dǎo)ObjectDescriptor類型為data():msg:string,methods:greet():string&ThisType接著借助推導(dǎo)出來的ObjectDescriptor推導(dǎo)出greet里的this類型為msg:string&greet():todo因此推導(dǎo)出this.msg類型為string,進一步推導(dǎo)出greet的類型為string,至此所有類型推完。另外為了減小Typescript的類型推倒難度,應(yīng)該盡可能的顯示的標注類型,防止出現(xiàn)循環(huán)推導(dǎo)或者造成推導(dǎo)復(fù)雜度變高等導(dǎo)致編譯速度過慢甚至出現(xiàn)死循環(huán)或者內(nèi)存耗盡的問題。typeObjectDescriptor

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論