TypeScript防脫發(fā)級入門——TS中的類

嗨!大家好!我是法醫(yī),一只治療系前端碼猿??,與代碼對話,傾聽它們心底的呼聲,期待著大家的點(diǎn)贊??與關(guān)注?。
1. 面向?qū)ο蟮母攀?/span>
說到類就不得不說面向?qū)ο罅?,這是因?yàn)門S為前端面向?qū)ο蟮拈_發(fā)帶來了契機(jī),由于JS沒有類型系統(tǒng),如果使用面向?qū)ο蠓绞介_發(fā)會產(chǎn)生大量的接口(不是指TS中的接口,而是指函數(shù)或方法),而大量的接口會導(dǎo)致接口調(diào)用復(fù)雜度增加,這種復(fù)雜度必須通過嚴(yán)格的類型檢查來避免錯誤,如果沒有嚴(yán)格的類型檢查,那么我們在調(diào)用過程中全憑記憶力,在寫代碼的過程中心都是懸著的??,沒有絲毫安全感可言???♂?。也正是因?yàn)槿绱?,JS語言并不適合大型項(xiàng)目的開發(fā),這是由JS本身特性決定的——解釋型和弱類型
TS帶來了完整的類型系統(tǒng),因此開發(fā)復(fù)雜應(yīng)用時,無論接口數(shù)量有多少,都可以獲得完整的類型檢查,并且這種檢查是具有強(qiáng)約束力的
面向?qū)ο?/code>這個詞已經(jīng)出來很久了,據(jù)說是Alan Kay提出來的,關(guān)于誰是面向?qū)ο笾敢彩怯袪幾h的,至于是誰,我想不用過多care,面向?qū)ο笾杏性S多成熟的模式,能處理各種復(fù)雜問題,畢竟在大型應(yīng)用復(fù)雜領(lǐng)域積累了非常多的經(jīng)驗(yàn),既然TS為前端面向?qū)ο蟮拈_發(fā)帶來了契機(jī),而前端開發(fā)也日益復(fù)雜,所以前端跟面向?qū)ο蟮慕Y(jié)合也是自然而然的事情
什么是面向?qū)ο螅?/p>
面向?qū)ο螅?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(145, 109, 213);font-weight: bolder;background-image: none;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;">object-oriented,簡稱OO,它是一種編程思想,它提出一切以劃分對象為出發(fā)點(diǎn)思考程序。當(dāng)然也有其它的編程思想。比如說:面向過程、函數(shù)式編程。面向過程是以功能流程為思考切入點(diǎn)的,不適用大型項(xiàng)目開發(fā),而函數(shù)式編程是以數(shù)學(xué)運(yùn)算為思考切入點(diǎn)的
2. 類的繼承
繼承可以描述類與類之間的關(guān)系,比如說:人是一個類,男人也是一個類,男人是人,則人和男人可以形成繼承關(guān)系
如果A和B都是類,并且可以描述為A是B,則A和B形成繼承關(guān)系,我們把B稱為父類,A稱為子類,當(dāng)然還有其它一些說法:
B是父類,A是子類 B派生A,A繼承自B B是A的基類,A是B的派生類
如果在書中或者文章中看到不同的說法不要慌??,它們表示同一個意思。繼承的好處在于子類會擁有父類所有的成員,這樣就可以減少很多重復(fù)代碼
2.1 成員的重寫
?? 重寫(override):無論是屬性還是方法,子類都可以重寫父類的相應(yīng)成員,但需要注意的是子類不能改變父類成員的類型,類型必須匹配
舉個例子??:子類重寫父類的屬性
export?class?Person{
????eyes:number?=?0
}
export?class?Man?extends?Person{
????eyes:number?=?2
????eyes:string?=?"2"?//報(bào)錯,子類不能修改父類的成員類型,父類是什么類型,子類必須是什么類型
}
const?m?=?new?Man();
console.log(m.eyes);//2
舉個例子??:子類重寫父類的方法
export?class?Person{
????eyes:number?=?0
????sayHello(){
????????console.log("你好,世界");
????????
????}
}
export?class?Man?extends?Person{
????eyes:number?=?2
????sayHello(){
????????console.log("我是男人,我真帥");??????
????}
}
const?m?=?new?Man();
m.sayHello();//我是男人,我真帥
2.2 this指向問題
?? 注意
this關(guān)鍵字:在繼承關(guān)系中,this的指向是動態(tài)的,它是根據(jù)具體的調(diào)用者來確定this指向
舉個例子??:this關(guān)鍵字的指向
export?class?Person{
????name:string?=?"上帝"
????sayHello(){
????????console.log(`你好,我叫${this.name}`);
????????
????}
}
export?class?Man?extends?Person{
????name:string?=?"仵法醫(yī)"
????sayHello(){
????????console.log(`你好,我叫${this.name}`);
????????
????}
}
const?m?=?new?Man();
m.sayHello();//由于這里是 m 調(diào)用的,它指向的是Man這個類,所以輸出:?你好,我叫仵法醫(yī)
2.3 super關(guān)鍵字
當(dāng)我們需要在子類中調(diào)用父類的方法時,可以使用
super關(guān)鍵字
舉個例子??:super關(guān)鍵字
export?class?Person?{
????name:?string?=?"上帝"
????sayHello()?{
????????console.log(`你好,我叫${this.name}`);
????}
}
export?class?Man?extends?Person?{
????name:?string?=?"仵法醫(yī)"
????test()?{?????
????????super.sayHello();//你好,我叫仵法醫(yī)
????????this.sayHello();//你好,我叫仵法醫(yī)
????}
}
const?m?=?new?Man();
m.test();
我想大家也看到了,當(dāng)使用super關(guān)鍵字調(diào)用父類函數(shù)sayHello的時候,super和this的效果是一樣的,但它是有一個前提的,就是子類沒有重寫父類sayHello函數(shù)的前提下是一樣的,只有子類重寫父類函數(shù)的時候,super和this才有差別
舉個例子??:重寫sayHello函數(shù),再看super關(guān)鍵字
export?class?Person?{
????name:?string?=?"上帝"
????sayHello()?{
????????console.log(`你好,我叫${this.name}`);
????}
}
export?class?Man?extends?Person?{
????name:?string?=?"仵法醫(yī)"
????sayHello()?{
????????console.log(`我是帥哥`);
????}
????test()?{?????
????????super.sayHello();//你好,我叫仵法醫(yī)
????????this.sayHello();//我是帥哥
????}
}
const?m?=?new?Man();
m.test();
2.4 繼承的特性
單根性:指子類只能繼承一個父類,不能同時繼承多個父類,如果想繼承多個父類,混入mixin了解一下
傳遞性:A繼承B,C繼承A,那么C同時擁有A和B的成員
3. 抽象類
3.1 為什么需要抽象類
?? 抽象類(
abstract)在JS中是沒有的,它是TS提出來的,有時候,某個類只表示抽象的概念,主要用于提取子類共有的成員,而不能直接創(chuàng)建它的對象,這時該類可以作為抽象類。只要給類前加上abstract就可以表示抽象類,抽象類不可以創(chuàng)建對象
3.2 抽象父類
舉個例子??:抽象父類 Person,表示人
abstract?class?Person?{
????
}
class?Man?extends?Person?{
????
}
class?Woman?extends?Person{
}
const?m?=?new?Man();
const?w?=?new?Woman();
3.3 抽象成員
?? 在父類中,可能知道有些成員是必須要存在的,比如說一個人的名字,每個人都有名字,但是我們沒有辦法在父類中直接書寫具體叫什么名,只能在子類對象中才能清楚知道,因此,需要一種強(qiáng)約束,讓繼承該父類的子類必須實(shí)現(xiàn)該成員
需要注意的是,只有在抽象類中,才可以有抽象成員,這些抽象成員必須在子類中時實(shí)現(xiàn),必須的必??
舉個例子??:抽象成員,子類實(shí)現(xiàn)
abstract?class?Person?{//抽象類
????abstract?readonly?name:?string;//抽象成員
}
/**
?*?playBoy?表示花花公子
?*/
class?playBoy?extends?Person?{
???readonly?name:?string?=?"老王";//子類實(shí)現(xiàn)抽象成員,第一種方式
}
/**
?*?prettyWoman?表示美麗的女人
?*/
class?prettyWoman?extends?Person?{
????readonly?name:?string;
????constructor()?{
????????super()
????????this.name?=?"翠花";//子類實(shí)現(xiàn)抽象成員,第二種方式
????}
}
/**
?*?twoTimer?表示愛情不專一的人
?*/
class?twoTimer?extends?Person?{
????//這里沒有寫?set?訪問器,所以本身就是只讀的,所以可以不用?readonly,也沒法用
????get?name():?string?{
????????return?"王小賤";//子類實(shí)現(xiàn)抽象成員,第三種方式
????}
}
const?pB?=?new?playBoy();
const?pW?=?new?prettyWoman();
const?tT?=?new?twoTimer();
console.log(pB.name,pW.name,tT.name);//老王?翠花?王小賤
4. 靜態(tài)成員
4.1 什么是靜態(tài)成員
?? 靜態(tài)成員就是附著在類上的成員,成員包括屬性和方法,如果在JS當(dāng)中,我們可以說附著在構(gòu)造函數(shù)上的成員。使用
static修飾的成員稱作靜態(tài)成員,靜態(tài)成員也稱作非實(shí)例成員,它是屬于某個類的,而實(shí)例成員也叫對象成員,它是屬于某個類的對象
舉個例子??:
class?Person?{
????name:?string?=?"前端獵手"
????age:?number?=?18
????static?sayHello(say:string){
????????console.log(`我想說${say}`);???????
????}?
}
const?res1?=?Person.sayHello("你好,世界!");//靜態(tài)方法必須通過類調(diào)用?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
console.log(res1);//我想說你好,世界!
const?res2?=?new?Person();//實(shí)例成員必須通過實(shí)例對象調(diào)用
console.log(res2.age,res2.name);//18?翠花
4.2 靜態(tài)方法中的this
?? 靜態(tài)方法中的
this指向當(dāng)前類,而實(shí)例方法中的this指向當(dāng)前對象
5. 索引器
對象[值],或者叫做成員表達(dá)式,在ts中,默認(rèn)情況下,不會對索引器(成員表達(dá)式做嚴(yán)格的類型檢查),使用配置noImplicitAny開啟對隱式any的檢查。隱式any:ts根據(jù)實(shí)際情況推導(dǎo)出的any類型
TS中索引器的作用
在嚴(yán)格的檢查下,可以實(shí)現(xiàn)為類動態(tài)增加成員 可以實(shí)現(xiàn)動態(tài)操作類成員
在js中,所有成員名本質(zhì)上,都是字符串,如果使用數(shù)字作為成員名,會自動轉(zhuǎn)換為字符串
在ts中,如果某個類中使用了兩種類型的索引器,要求兩種索引器的值類型必須匹配
最后
很感謝小伙伴看到最后??,如果您覺得這篇文章有幫助到您的的話不妨關(guān)注?+點(diǎn)贊??+收藏??+評論??,您的支持就是我更新的最大動力。
