TypeScript入門——擴(kuò)展類型之枚舉

?? 擴(kuò)展類型——枚舉
在上一篇文章中聊到了很多TS基礎(chǔ)類型,那為什么又出現(xiàn)了擴(kuò)展類型枚舉,我們都知道任何東西都不是平白無故就出現(xiàn)的,都是為了解決特定的問題。枚舉只是擴(kuò)展類型其中之一,比如說還有類型別名,接口,類
那么枚舉是什么意思呢?
??
枚舉就是把一卡車西瓜一個(gè)一個(gè)擺在攤子上的過程。
有什么作用?
??
枚舉通常用來約束某個(gè)變量的取值范圍,當(dāng)然不僅僅是變量,還有函數(shù)的參數(shù)或者函數(shù)的返回值,比如說約束變量sex性別的范圍,不是男就是女了,不可能是不男不女吧??
看過我上一篇文章的小伙伴也許會回憶到當(dāng)時(shí)文章中也定義了變量gender性別取值范圍,當(dāng)時(shí)是用字面量配合聯(lián)合類型處理的
舉個(gè)栗子??:
//通過字面量配合聯(lián)合類型也能達(dá)到約束變量的目的
let gender : "男" | "女";
字面量配合聯(lián)合類型也能達(dá)到約束變量的目的,那么它和枚舉有什么區(qū)別呢?不用想,肯定是遇到解決不了的問題,否則整個(gè)枚舉出來多此一舉沒意義。接下來我會詳細(xì)地介紹,你可以學(xué)到:
枚舉出現(xiàn)的契機(jī)是什么 它解決了什么問題
? 字面量類型的問題
?? 1. 在類型約束位置會產(chǎn)生重復(fù)代碼,可以使用類型別名解決該問題
舉個(gè)栗子??:
我們在代碼中定義一個(gè)gender變量,類型約束為男或者女,gender只能賦值男或者女,其它值不行,接下來有個(gè)查詢用戶的函數(shù)searchUsers,這個(gè)函數(shù)是根據(jù)性別進(jìn)行查詢用戶的,如下:
//定義一個(gè)gender變量,并且約束為男或者女
let gender : "男" | "女";
//gender可以賦值為男或者女
gender = "女";
gender = "男";
//根據(jù)性別查詢函數(shù)
function searchUsers(g:"男" | "女") {
}
從代碼中可以看到變量gender約束跟函數(shù)參數(shù)約束產(chǎn)生相同代碼"男" | "女",看過上一篇文章的小伙伴也許已經(jīng)按捺不住了,因?yàn)樯弦黄恼绿岬竭^一個(gè)類型別名,它是可以解決這個(gè)問題的,如下:
//定義一個(gè)類型別名
type Gender = "男" | "女";
//定義一個(gè)gender變量,并且約束為男或者女
let gender : Gender;
//gender可以賦值為男或者女
gender = "女";
gender = "男";
//根據(jù)性別查詢函數(shù)
function searchUsers(g:Gender) {
}
所以在類型約束位置會產(chǎn)生重復(fù)代碼,可以使用類型別名解決該問題。但是其它問題是沒有辦法通過類型別名來解決的
?? 2. 邏輯含義和真實(shí)的值產(chǎn)生了混淆,會導(dǎo)致當(dāng)修改真實(shí)值的時(shí)候,產(chǎn)生大量修改
舉個(gè)栗子??:
//定義一個(gè)類型別名
type Gender = "男" | "女";
//定義一個(gè)gender變量,并且約束為男或者女
let gender : Gender;
//gender可以賦值為男或者女
gender = "女";
gender = "男";
//根據(jù)性別查詢函數(shù)
function searchUsers(g:Gender) {
}
上面代碼中定義了類型別名Gender并且約束為男或者女,在后續(xù)寫代碼過程中,肯定會給gender賦值男或女,我們可以想象在幾萬行代碼中大量用到gender變量進(jìn)行賦值,有一天沒吃藥的產(chǎn)品經(jīng)理提了個(gè)需求:性別用男女約束太俗了,顯得沒有檔次,換個(gè)美女和帥哥,如下:
//定義一個(gè)類型別名
type Gender = "帥哥" | "美女";
//定義一個(gè)gender變量,并且約束為男或者女
let gender : Gender;
//gender可以賦值為男或者女
gender = "女";
gender = "男";
//根據(jù)性別查詢函數(shù)
function searchUsers(g:Gender) {
}
換成美女和帥哥后是不是要瘋了,幾十萬行代碼中大量使用了變量gender賦值為字面量,約束名一改,后面所有用到的地方都要跟著改,產(chǎn)生大量的修改,為什么會這樣呢?根本原因是將邏輯含義和真實(shí)的值混淆在了一起,目前約束的美女和帥哥是真實(shí)的值,但不管是帥哥、美女,還是男、女都是一個(gè)含義,都表示生物學(xué)上的性別男和女,使用字面量類型的時(shí)候會導(dǎo)致真實(shí)的值和邏輯含義的值是對應(yīng)的,但是在給變量賦值的時(shí)候只能賦值為真實(shí)的值,邏輯含義的值不變,但真實(shí)的值卻變了,就產(chǎn)生了大量的修改,這個(gè)問題靠類型別名是沒法解決的
?? 3. 字面量類型不會進(jìn)入到編譯結(jié)果
字面量類型是不會參與編譯,運(yùn)行完成后會消失,如下:

如果我們想在TS中動態(tài)讀取變量中有哪些取值并顯示在頁面上,是做不到的,因?yàn)?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;">TS在編譯的時(shí)候已經(jīng)丟失了變量約束信息。
第二個(gè)和第三個(gè)問題想要解決就需要靠枚舉了
?? 枚舉的 “道”
?? 1. 如何定義一個(gè)枚舉?
//枚舉字段表示性別有哪些取值
enum 枚舉名 {
枚舉字段1:值1,
枚舉字段2:值2,
枚舉字段3:值3,
}
//以性別為例
enum Gender {
male = "美女",
female = "帥哥",
}
從上述枚舉定義來看,控而已發(fā)現(xiàn)有兩個(gè)值,一個(gè)枚舉字段名,另一個(gè)就是值,之所以會有兩個(gè)值,就是解決邏輯含義和真實(shí)的值所產(chǎn)生的混淆,而在枚舉中將邏輯含義和真實(shí)的值分開了,左邊是邏輯含義值,右邊是真實(shí)的值,有了枚舉之后就不再需要類型別名了,對字面量類型出現(xiàn)問題的代碼進(jìn)行修改:
//定義一個(gè)類型別名
//type Gender = "帥哥" | "美女";
//換成枚舉
enum Gender {
male = "美女",
female = "帥哥",
}
//定義一個(gè)gender變量,并且約束為男或者女
let gender : Gender;
//gender可以賦值為男或者女
//gender = "女";
//gender = "男";
//使用了枚舉之后,就不能用真實(shí)的值進(jìn)行賦值了
gender = Gender.male;
gender = Gender.female;
//根據(jù)性別查詢函數(shù)
function searchUsers(g:Gender) {
}
如此就解決了字面量類型中第二個(gè)問題:邏輯含義和真實(shí)的值產(chǎn)生的混淆,一旦修改真實(shí)的值,造成后續(xù)大量代碼的修改。使用了枚舉之后將來直接修改真實(shí)的值就可以了,僅需要改一個(gè)地方即可,因?yàn)楹罄m(xù)所有的代碼都是用的是邏輯含義的值,這是不會變化的。
枚舉另外一個(gè)好處就是,枚舉會參與代碼的編譯,它會出現(xiàn)編譯的結(jié)果中,枚舉在JS中表現(xiàn)為對象,如下:

由于TS中使用了中文,所以它會進(jìn)行unicode編碼,編譯后的JS文件中,首先聲明了一個(gè)變量Gender,然后將Gender傳入函數(shù),如果Gender沒有值,那么賦值為一個(gè)對象,隨后給對象中添加一條屬性male,賦值為美女,以及female賦值為帥哥,因此可以發(fā)現(xiàn)枚舉是會參與代碼的編譯,所以我們能在代碼編譯運(yùn)行階段動態(tài)的打印枚舉中的屬性值。如下:

然而之前的類型別名是做不到的,因?yàn)轭愋蛣e名在編譯的時(shí)候會消失,而枚舉則不會。
因此如果我們需要在運(yùn)行的過程中使用某個(gè)取值范圍的話,應(yīng)該使用枚舉,而且防止未來修改大量的代碼,應(yīng)當(dāng)將邏輯含義跟真實(shí)的值分開,也應(yīng)當(dāng)使用枚舉
?? 緊急通知: 翠花小姐姐來了
翠花小姐姐提了一個(gè)問題:那我們該何時(shí)用類型別名?有何時(shí)用枚舉呢?
?? 解答:
實(shí)際上不用糾結(jié),只要是取值范圍都可以用枚舉,用它準(zhǔn)沒錯(cuò)??
?? 2. 枚舉的規(guī)則
枚舉的值可以是字符串或數(shù)字
字符串剛剛已經(jīng)說過了,枚舉性別用的就是字符串,我們把值為數(shù)字的稱為
數(shù)字枚舉數(shù)字枚舉的值會自動自增,只有數(shù)字有這個(gè)特點(diǎn)
舉個(gè)栗子??:
定義了一個(gè)
data枚舉,是周一到星期天的字段值,當(dāng)給Monday賦值為1時(shí),其它值會根據(jù)上一個(gè)值依次自增,如果第一個(gè)值沒有賦值,那么它會從0開始,
數(shù)字枚舉的編譯結(jié)果和字符串枚舉編譯的結(jié)果有差異
這是數(shù)字枚舉編譯后的結(jié)果

?? 3. 枚舉的最佳實(shí)踐
盡量不要在一個(gè)枚舉中既出現(xiàn)字符串字段,又出現(xiàn)數(shù)字字段 使用枚舉時(shí),盡量使用枚舉字段的名稱,而不使用真實(shí)的值,就是把邏輯的值和真實(shí)的值分開 能用枚舉就用枚舉,使用類型別名,那兩個(gè)問題逃不掉
