国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

為什么TypeScript的Enum會(huì )出現問(wèn)題

發(fā)布時(shí)間:2021-08-17 12:16 來(lái)源: 閱讀:0 作者:小紅星閃啊閃 欄目: JavaScript 歡迎投稿:712375056

目錄

TypeScript引入了很多靜態(tài)編譯語(yǔ)言的特性,比如class(現在是JavaScript的一部分了),interface, generics和union types等。

但是今天有一個(gè)類(lèi)型需要著(zhù)重討論下,這就是enum。

對于很多的靜態(tài)語(yǔ)言來(lái)說(shuō),枚舉是一個(gè)很非常常見(jiàn)的語(yǔ)言特性。比如,c,c#,java和swift。枚舉就是你在代碼里可以用的一組常量。

我們用TypeScript來(lái)新建一個(gè)enum來(lái)代表一周的幾天:

enum DayOfWeek {
  Sunday,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday
};

這個(gè)枚舉使用enum關(guān)鍵字聲明,后面跟著(zhù)DayOfWeek名稱(chēng)。然后我們定義枚舉里可以使用的常量。

現在我們定義一個(gè)方法,接受這個(gè)枚舉類(lèi)型的參數,來(lái)判斷傳入的參數是不是周末。

function isItTheWeekend(day: DayOfWeek) {
  switch (day) {
    case DayOfWeek.Sunday:
    case DayOfWeek.Saturday:
      return true;
 
    default:
      return false;
  }
}

最后,我們可以這要用:

console.log(isItTheWeekend(DayOfWeek.Monday)); // log: false

對于消除程序里的魔法字符串來(lái)說(shuō),這是一個(gè)非常有用的方法。

但是,事情遠不是我們想的這么簡(jiǎn)單。下面的代碼調用會(huì )在TypeScript編譯之后得到什么呢?

console.log(isItTheWeekend(2)); // is this valid?

知道結果你會(huì )嚇一跳。這樣的調用是符合TypeScript規則的,編譯器也會(huì )順利編譯。

發(fā)生了什么呢?

上面的情況可能會(huì )讓你認為你發(fā)現了一個(gè)TypeScript的bug。其實(shí)TypeScript就是這么設計的。

我們這里新建了一個(gè)數字枚舉,而且我們可以在TypeScript Playground里看看編譯出來(lái)的結果是什么:

var DayOfWeek;
(function (DayOfWeek) {
    DayOfWeek[DayOfWeek["Sunday"] = 0] = "Sunday";
    DayOfWeek[DayOfWeek["Monday"] = 1] = "Monday";
    DayOfWeek[DayOfWeek["Tuesday"] = 2] = "Tuesday";
    DayOfWeek[DayOfWeek["Wednesday"] = 3] = "Wednesday";
    DayOfWeek[DayOfWeek["Thursday"] = 4] = "Thursday";
    DayOfWeek[DayOfWeek["Friday"] = 5] = "Friday";
    DayOfWeek[DayOfWeek["Saturday"] = 6] = "Saturday";
})(DayOfWeek || (DayOfWeek = {}));

運行結果是:

事實(shí)上枚舉就是一個(gè)JavaScript對象。

這個(gè)對象的屬性就是根據我進(jìn)定義的枚舉常量生成,還根據定義的順序生成了對應的數字(順序,Sunday是0,Saturday是6)。這個(gè)對象也有數字作為key,對應的常量字符串作為值的屬性。

因此,我們可以給上面的方法傳入數字,數字映射到對應的枚舉值。枚舉既是一個(gè)數字常量也是一個(gè)字符串常量。

什么時(shí)候用

如果一個(gè)方法接收一個(gè)枚舉類(lèi)型參數,但是一個(gè)任意的數字就可以通過(guò)編譯的話(huà)。這樣的結果顯然破壞了TypeScript構建的類(lèi)型安全體系。這什么時(shí)候可以用呢?

假設你有一個(gè)服務(wù)返回一個(gè)JSON串,你想把這個(gè)串建模,對應的某個(gè)屬性是一個(gè)枚舉。

在你的數據里存的是數字。定義一個(gè)TypeScript枚舉可以很容易解決這個(gè)問(wèn)題:

const day: DayOfWeek = 3;

這個(gè)在賦值時(shí)執行的顯示的類(lèi)型轉換會(huì )把數字轉換成枚舉的對應常量。也就是說(shuō)我們在代碼里使用這個(gè)枚舉會(huì )讓代碼更容易讀懂。

控制枚舉的數字

枚舉的成員對應的數字是根據枚舉常量定義的順序生成的。那我們是否可以控制這個(gè)數字的值呢?是可以的。

enum FileState {
  Read = 1,
  Write = 2
}

只是描述一個(gè)文件可能的狀態(tài)的枚舉。

它可能是讀也可能是寫(xiě)狀態(tài),我們顯示的定義了枚舉值?,F在就很明確什么樣的值是合理的,因為顯示定義了。

Bit值

但是還有另一個(gè)情況很有用,位值(Bit)。

我們再來(lái)看一下這個(gè)FileState枚舉,給它添加一個(gè)新的枚舉值ReadWrite:

enum FileState {
  Read = 1,
  Write = 2,
  ReadWrite = 3
}

之后假設有一個(gè)方法接受這個(gè)類(lèi)型的參數:

const file = await getFile("/path/to/file", FileState.Read | FileState.Write);

我們在FileState上使用了|操作符。這樣我們可以使用位運算來(lái)獲得一個(gè)新的枚舉值。在這個(gè)例子里面就是3,ReadWrite的值。

事實(shí)上,我們可以寫(xiě)的更清楚一些:

enum FileState {
  Read = 1,
  Write = 2,
  ReadWrite = Read | Write
}

這個(gè)ReadWrite的值不是寫(xiě)死的,而是位運算得到的。

但是再這樣使用枚舉的時(shí)候要多加小心。

如下的枚舉:

enum Foo {
  A = 1,
  B = 2,
  C = 3,
  D = 4,
  E = 5
}

如果要得到E(或者5),可以位運算得到么:Foo.A | Foo.D or Foo.B | Foo.C?

所以如果要用枚舉值做位運算,那么明確如何得到這個(gè)值。

控制索引

一般情況下,每個(gè)枚舉值都會(huì )有一個(gè)默認的數字值。如果需要也可以明確的給這些枚舉值賦值。另外,還可以給某部分枚舉賦值:

enum DayOfWeek {
  Sunday,
  Monday,
  Tuesday,
  Wednesday = 10,
  Thursday,
  Friday,
  Saturday
}

前幾個(gè)值是按照位置賦值,Sunday到TuesDay是0到2.之后在Wednesday給了一個(gè)新值,從這開(kāi)始每個(gè)值都遞增1. 這就可能會(huì )出現問(wèn)題了:

enum DayOfWeek {
  Sunday,
  Monday,
  Tuesday,
  Wednesday = 10,
  Thursday = 2,
  Friday,
  Saturday
}

Tuesday賦值為2,生成的JavaScript是什么樣子呢:

var DayOfWeek;
(function (DayOfWeek) {
    DayOfWeek[DayOfWeek["Sunday"] = 0] = "Sunday";
    DayOfWeek[DayOfWeek["Monday"] = 1] = "Monday";
    DayOfWeek[DayOfWeek["Tuesday"] = 2] = "Tuesday";
    DayOfWeek[DayOfWeek["Wednesday"] = 10] = "Wednesday";
    DayOfWeek[DayOfWeek["Thursday"] = 2] = "Thursday";
    DayOfWeek[DayOfWeek["Friday"] = 3] = "Friday";
    DayOfWeek[DayOfWeek["Saturday"] = 4] = "Saturday";
})(DayOfWeek || (DayOfWeek = {}));

看起來(lái)Tuesday和Thursday的數值都是2。

所以,需要顯示的設定數值。

非數字枚舉

目前為止,我們只討論了數值枚舉,但是枚舉的值不一定非的是數字。它也可以是任何常量或者計算值:

enum DayOfWeek {
  Sunday = "Sun",
  Monday = "Mon",
  Tuesday = "Tues",
  Wednesday = "Wed",
  Thursday = "Thurs",
  Friday = "Fri",
  Saturday = "Sat"
}

現在就不能給isItTheWeekend方法穿數字參數了。這個(gè)枚舉已經(jīng)不再是數字枚舉。然而,我們也不能傳任意字符串進(jìn)去,因為枚舉知道什么樣的值才是合理的。

這樣也帶來(lái)另外一個(gè)問(wèn)題:

const day: DayOfWeek = "Mon";

這樣是行不通的。

字符串并不能直接給枚舉賦值,而是需要一個(gè)顯示的類(lèi)型轉換:

const day = "Mon" as DayOfWeek;
能不能給它賦其他值呢?事實(shí)上枚舉可以有很多類(lèi)型的值:

enum Confusing {
  A,
  B = 1,
  C = 1 << 8,
  D = 1 + 2,
  E = "Hello World".length
}

這個(gè)例子的枚舉值都是數字。但是這些數字值可以直接賦值,也可以是計算值,或者是字符串的length屬性。如果都是常量的話(huà),那么就可以是多種類(lèi)型的值:

enum MoreConfusion {
  A,
  B = 2,
  C = "C"
}

這種情況就很難讓人理解枚舉后面的數據是怎么工作的。所以,最好不要用這樣的枚舉。

結論

TypeScript的枚舉是對JavaScript的一個(gè)很好地補充,使用得當將非常有用。它將有助于清理代碼中存在的魔術(shù)值(magic values)字符串、數字。而且它是類(lèi)型安全的。

到此這篇關(guān)于為什么TypeScript的Enum會(huì )出現問(wèn)題的文章就介紹到這了,更多相關(guān)TypeScript Enum內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

日本精品ΑV中文字幕| 精品久久久久久亚洲精品| 日本簧片在线观看| 国产Av无码专区亚洲版综合| 毛色毛片免费观看| china熟女熟妇乱老女人|