官术网_书友最值得收藏!

5.4.5 常量枚舉成員與計算枚舉成員

每個枚舉成員都有一個值,根據枚舉成員值的定義可以將枚舉成員劃分為以下兩類:

?常量枚舉成員

?計算枚舉成員

5.4.5.1 常量枚舉成員

若枚舉類型的第一個枚舉成員沒有定義初始值,那么該枚舉成員是常量枚舉成員并且初始值為0。示例如下:


01 enum Foo {
02     A,   // 0
03 }

此例中,枚舉成員A是常量枚舉成員,并且“Foo.A”的值為0。

若枚舉成員沒有定義初始值并且與之緊鄰的前一個枚舉成員值是數值型常量,那么該枚舉成員是常量枚舉成員并且初始值為緊鄰的前一個枚舉成員值加1。如果緊鄰的前一個枚舉成員的值不是數值型常量,那么將產生錯誤。示例如下:


01 enum Foo {
02     A,        // 0
03     B,        // 1
04 }
05 
06 enum Bar {
07     C = 'C',
08     D,        // 編譯錯誤
09 }

此例中,枚舉成員“Foo.A”和“Foo.B”都是常量枚舉成員。枚舉成員“Bar.D”的定義將產生編譯錯誤,因為它沒有指定初始值并且前一個枚舉成員“Bar.C”的值不是數值。

若枚舉成員的初始值是常量枚舉表達式,那么該枚舉成員是常量枚舉成員。常量枚舉表達式是TypeScript表達式的子集,它能夠在編譯階段被求值。常量枚舉表達式的具體規則如下:

?常量枚舉表達式可以是數字字面量、字符串字面量和不包含替換值的模板字面量。

?常量枚舉表達式可以是對前面定義的常量枚舉成員的引用。

?常量枚舉表達式可以是用分組運算符包圍起來的常量枚舉表達式。

?常量枚舉表達式中可以使用一元運算符“+”“-”“~”,操作數必須為常量枚舉表達式。

?常量枚舉表達式中可以使用二元運算符“+”“-”“*”“**”“/”“%”“<<”“>>”“>>>”“&”“|”“^”,兩個操作數必須為常量枚舉表達式。

例如,下例中的枚舉成員均為常量枚舉成員:


01 enum Foo {
02     A = 0,           // 數字字面量
03     B = 'B',         // 字符串字面量
04     C = `C`,         // 無替換值的模板字面量
05     D = A,           // 引用前面定義的常量枚舉成員
06 }
07 
08 enum Bar {
09     A = -1,          // 一元運算符
10     B = 1 + 2,       // 二元運算符
11     C = (4 / 2) * 3, // 分組運算符(小括號)
12 }

字面量枚舉成員是常量枚舉成員的子集。字面量枚舉成員是指滿足下列條件之一的枚舉成員,具體條件如下:

?枚舉成員沒有定義初始值。

?枚舉成員的初始值為數字字面量、字符串字面量和不包含替換值的模板字面量。

?枚舉成員的初始值為對其他字面量枚舉成員的引用。

下例中,Foo枚舉的所有成員都是字面量枚舉成員,同時它們也都是常量枚舉成員:


01 enum Foo {
02     A,
03     B = 1,
04     C = -3,
05     D = 'foo',
06     E = `bar`,
07     F = A
08 }

5.4.5.2 計算枚舉成員

除常量枚舉成員之外的其他枚舉成員都屬于計算枚舉成員。下例中,枚舉成員“Foo.A”和“Foo.B”均為計算枚舉成員:


01 enum Foo {
02     A = 'A'.length,
03     B = Math.pow(2, 3)
04 }

5.4.5.3 使用示例

枚舉表示一組有限元素的集合,并通過枚舉成員名來引用集合中的元素。有時候,程序中并不關注枚舉成員值。在這種情況下,讓TypeScript去自動計算枚舉成員值是很方便的。示例如下:


01 enum Direction {
02     Up,
03     Down,
04     Left,
05     Right,
06 }
07 
08 function move(direction: Direction) {
09     switch (direction) {
10         case Direction.Up:
11             console.log('Up');
12             break;
13         case Direction.Down:
14             console.log('Down');
15             break;
16         case Direction.Left:
17             console.log('Left');
18             break;
19         case Direction.Right:
20             console.log('Right');
21             break;
22     }
23 }
24 
25 move(Direction.Up);   // 'Up'
26 move(Direction.Down); // 'Down'

程序不依賴枚舉成員值時,能夠降低代碼耦合度,使程序易于擴展。例如,我們想給Direction枚舉添加一個名為None的枚舉成員來表示未知方向。按照慣例,None應作為第一個枚舉成員。因此,我們可以將代碼修改如下:


01 enum Direction {
02     None,
03     Up,
04     Down,
05     Left,
06     Right,
07 }
08 
09 function move(direction: Direction) {
10     switch (direction) {
11         case Direction.None:
12             console.log('None');
13             break;
14         case Direction.Up:
15             console.log('Up');
16             break;
17         case Direction.Down:
18             console.log('Down');
19             break;
20         case Direction.Left:
21             console.log('Left');
22             break;
23         case Direction.Right:
24             console.log('Right');
25             break;
26     }
27 }
28 
29 move(Direction.Up);   // 'Up'
30 move(Direction.Down); // 'Down'
31 move(Direction.None); // 'None'

此例中,枚舉成員Up、Down、Left和Right的值已經發生了改變,Up的值由0變為1,以此類推。由于move()函數的行為不直接依賴枚舉成員的值,因此本次代碼修改對move()函數的已有功能不產生任何影響。但如果程序中依賴了枚舉成員的具體值,那么這次代碼修改就會破壞現有的代碼,如下所示:


01 enum Direction {
02     None,
03     Up,
04     Down,
05     Left,
06     Right,
07 }
08 
09 function move(direction: Direction) {
10     switch (direction) {
11         // 不會報錯,但是邏輯錯誤,Direction.Up的值已經不是數字0
12         case 0:
13             console.log('Up');
14             break;
15 
16         // 省略其他代碼
17     }
18 }

主站蜘蛛池模板: 鄢陵县| 乌审旗| 平南县| 濮阳市| 富川| 盘锦市| 上饶市| 武义县| 海阳市| 台山市| 钦州市| 简阳市| 论坛| 德惠市| 杭州市| 龙里县| 灵台县| 云南省| 巧家县| 防城港市| 东乡族自治县| 安福县| 兰西县| 酒泉市| 乐平市| 巴里| 虹口区| 侯马市| 买车| 沐川县| 保康县| 涞源县| 岐山县| 太湖县| 德庆县| 清苑县| 上思县| 南投市| 荣成市| 宣威市| 博乐市|