TypeScript 枚舉(Enum)
本節(jié)介紹枚舉類型的定義及其使用,需要定義一組相同主題的常量數(shù)據(jù)時,應(yīng)該立即想到枚舉類型。在學(xué)習(xí)過程中,需要注意枚舉類型的正向映射和反向映射,可以通過編譯后的 JavaScript 源碼進行分析,為什么可以進行反向映射。
1. 慕課解釋
使用枚舉我們可以定義一些帶名字的常量。TypeScript 支持數(shù)字的和基于字符串的枚舉。
2. 定義及使用場景
枚舉類型彌補了 JavaScript 的設(shè)計不足,很多語言都擁有枚舉類型。
當我們需要一組相同主題下的數(shù)據(jù)時,枚舉類型就很有用了。
enum Direction { Up, Down, Left, Right }
enum Months { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }
enum Size { big = '大', medium = '中', small = '小' }
enum Agency { province = 1, city = 2, district = 3 }
代碼解釋:
代碼中通過枚舉類型分別聲明了:不同的 方向
,一年內(nèi)不同的 月份
,一個商品的不同 尺寸屬性
,經(jīng)銷商的不同 級別
,這樣的一組常量數(shù)據(jù),是在一個相同主題下的不同表示。
3. 數(shù)字枚舉與字符串枚舉
聲明一個枚舉類型,如果沒有賦值,它們的值默認為數(shù)字類型且從 0 開始累加:
enum Months {
Jan,
Feb,
Mar,
Apr
}
Months.Jan === 0 // true
Months.Feb === 1 // true
Months.Mar === 2 // true
Months.Apr === 3 // true
現(xiàn)實中月份是從 1 月開始的,那么只需要這樣:
// 從第一個數(shù)字賦值,往后依次累加
enum Months {
Jan = 1,
Feb,
Mar,
Apr
}
Months.Jan === 1 // true
Months.Feb === 2 // true
Months.Mar === 3 // true
Months.Apr === 4 // true
代碼解釋:
第 3 行,從屬性 Jan
被賦值為 1
開始,后續(xù)的屬性值依次累加。
枚舉類型的值為字符串類型:
enum TokenType {
ACCESS = 'accessToken',
REFRESH = 'refreshToken'
}
// 兩種不同的取值寫法
console.log(TokenType.ACCESS === 'accessToken') // true
console.log(TokenType['REFRESH'] === 'refreshToken') // true
代碼解釋: 枚舉的取值,有 TokenType.ACCESS
和 TokenType['ACCESS']
這兩種不同的寫法,效果是相同的。
數(shù)字類型和字符串類型可以混合使用,但是不建議:
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
4. 計算常量成員
枚舉類型的值可以是一個簡單的計算表達式:
enum Calculate {
a,
b,
expired = 60 * 60 * 24,
length = 'imooc'.length,
plus = 'hello ' + 'world'
}
console.log(Calculate.expired) // 86400
console.log(Calculate.length) // 5
console.log(Calculate.plus) // hello world
Tips:
- 計算結(jié)果必須為常量。
- 計算項必須放在最后。
5. 反向映射
所謂的反向映射就是指枚舉的取值,不但可以正向的 Months.Jan
這樣取值,也可以反向的 Months[1]
這樣取值。
enum Months {
Jan = 1,
Feb,
Mar,
Apr
}
將上面的代碼進行編譯,查看編譯后的 JavaScript 代碼:
'use strict'
var Months;
(function (Months) {
Months[Months['Jan'] = 1] = 'Jan'
Months[Months['Feb'] = 2] = 'Feb'
Months[Months['Mar'] = 3] = 'Mar'
Months[Months['Apr'] = 4] = 'Apr'
})(Months || (Months = {}))
通過查看編譯后的代碼,可以得出:
console.log(Months.Mar === 3) // true
// 那么反過來能取到 Months[3] 的值嗎?
console.log(Months[3]) // 'Mar'
// 所以
console.log(Months.Mar === 3) // true
console.log(Months[3] === 'Mar') // true
Tips:
- 字符串枚舉成員不會生成反向映射。
- 枚舉類型被編譯成一個對象,它包含了正向映射( name -> value)和反向映射( value -> name)。
6. const 枚舉
在枚舉上使用 const
修飾符:
enum Months {
Jan = 1,
Feb,
Mar,
Apr
}
const month = Months.Mar
查看一下編譯后的內(nèi)容:
'use strict'
const month = 3 /* Mar */
發(fā)現(xiàn)枚舉類型應(yīng)該編譯出的對象沒有了,只剩下 month
常量。這就是使用 const
關(guān)鍵字聲明枚舉的作用。因為變量 month
已經(jīng)使用過枚舉類型,在編譯階段 TypeScript 就將枚舉類型抹去,這也是性能提升的一種方案。
7. 枚舉合并
分開聲明名稱相同的枚舉類型,會自動合并:
enum Months {
Jan = 1,
Feb,
Mar,
Apr
}
enum Months {
May = 5,
Jun
}
console.log(Months.Apr) // 4
console.log(Months.Jun) // 6
編譯后的 JavaScript 代碼:
'use strict'
var Months;
(function (Months) {
Months[Months['Jan'] = 1] = 'Jan'
Months[Months['Feb'] = 2] = 'Feb'
Months[Months['Mar'] = 3] = 'Mar'
Months[Months['Apr'] = 4] = 'Apr'
})(Months || (Months = {}));
(function (Months) {
Months[Months['May'] = 5] = 'May'
Months[Months['Jun'] = 6] = 'Jun'
})(Months || (Months = {}))
console.log(Months.Apr) // 4
console.log(Months.Jun) // 6
8. 小結(jié)
通過本節(jié)的介紹需要知道:
- 通過關(guān)鍵字
enum
來聲明枚舉類型。 - TypeScript 僅支持基于數(shù)字和字符串的枚舉。
- 通過枚舉類型編譯后的結(jié)果,了解到其本質(zhì)上就是 JavaScript 對象。