Typescript 實戰 --- (2)枚舉


枚舉(Enum)是一個命名元素的集合,用於取值被限定在一定范圍內的場景。
 
作用:將程序中不容易記憶的硬編碼,或者是在未來會發生改變的常量抽取出來,定義成枚舉類型,以此來提高程序的可讀性和可維護性
 
語法:
enum 枚舉類名 {
    枚舉成員1, 枚舉成員2, 枚舉成員3... ... 枚舉成員n;
  }

 

1、數字枚舉
使用枚舉可以定義一些有名字的數字常量,枚舉類型會被編譯成一個雙向映射的對象。枚舉成員會被賦值為從0開始遞增的數字,同時,也會被枚舉值到枚舉名進行反向映射
enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }

console.log('Days', Days);

// { 
//   '0': 'Sun',
//   '1': 'Mon',
//   '2': 'Tue',
//   '3': 'Wed',
//   '4': 'Thu',
//   '5': 'Fri',
//   '6': 'Sat',
//   Sun: 0,
//   Mon: 1,
//   Tue: 2,
//   Wed: 3,
//   Thu: 4,
//   Fri: 5,
//   Sat: 6 
// }

console.log('Days[0]:', Days[0]);   // Days[0]: Sun
console.log('Days.Sun:', Days.Sun); // Days.Sun: 0
console.log('Days[Days.Sun]:', Days[Days.Sun])  // Days[Days.Sun]: Sun

 

上例中,枚舉類Days被編譯成了一個js對象,該對象首先以枚舉名為key,以數字常量為value,逐對新增;然后以數字常量為key,枚舉值為value,逐對新增。由此,建立了一個枚舉值和數字常量雙向映射的對象

var Days;
(function (Days) {
    Days[Days["Sun"] = 0] = "Sun";
    Days[Days["Mon"] = 1] = "Mon";
    Days[Days["Tue"] = 2] = "Tue";
    Days[Days["Wed"] = 3] = "Wed";
    Days[Days["Thu"] = 4] = "Thu";
    Days[Days["Fri"] = 5] = "Fri";
    Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

 

默認情況下,第一個枚舉成員的值是0,后面的枚舉成員的值依次加1。也可以
enum Color1 { Red, Green, Blue };
enum Color2 { Red = 2, Green, Blue };
enum Color3 { Red, Green = 3, Blue };
enum Color4 { Red, Green, Blue = 0 }; // 不建議
enum Color5 { Red = -5, Green, Blue = 0 }; // 不建議
enum Color6 { Red = -6, Green, Blue };

console.log('Color1: ', Color1);
console.log('Color2: ', Color2);
console.log('Color3: ', Color3);
console.log('Color4: ', Color4);
console.log('Color5: ', Color5);
console.log('Color6: ', Color6);

// Color1:  { '0': 'Red', '1': 'Green', '2': 'Blue', Red: 0, Green: 1, Blue: 2 }
// Color2:  { '2': 'Red', '3': 'Green', '4': 'Blue', Red: 2, Green: 3, Blue: 4 }
// Color3:  { '0': 'Red', '3': 'Green', '4': 'Blue', Red: 0, Green: 3, Blue: 4 }
// Color4:  { '0': 'Blue', '1': 'Green', Red: 0, Green: 1, Blue: 0 }
// Color5:  { '0': 'Blue', Red: -5, '-5': 'Red', Green: -4, '-4': 'Green', Blue: 0 }
// Color6:  { Red: -6, '-6': 'Red', Green: -5, '-5': 'Green', Blue: -4, '-4': 'Blue' }

 

2、字符串枚舉
字符串枚舉是不可以做雙向映射的,只有枚舉成員的名稱作為key
enum OrderStatus {
  Created = '已創建',
  Cancelled = '已取消'
}

// 編譯
var OrderStatus;
(function (OrderStatus) {
    OrderStatus["Created"] = "\u5DF2\u521B\u5EFA";
    OrderStatus["Cancelled"] = "\u5DF2\u53D6\u6D88";
})(OrderStatus || (OrderStatus = {}));


console.log(OrderStatus);
// { Created: '已創建', Cancelled: '已取消' }

 

3、異構枚舉
把數字枚舉和字符串枚舉混用,就形成了異構枚舉,這種方式很容易引起混淆,不推薦使用
enum Result {
  T,
  F = "不通過"
}

// 編譯
var Result;
(function (Result) {
    Result[Result["T"] = 0] = "T";
    Result["F"] = "\u4E0D\u901A\u8FC7";
})(Result || (Result = {}));

console.log(Result);
{ '0': 'T', T: 0, F: '不通過' }

 

4、枚舉成員的特性
4-1、枚舉成員的值不可修改
Char.a = 6;  // Cannot assign to 'a' because it is a read-only property
 
4-2、枚舉成員的分類
(1)、常量枚舉:沒有設置初始值,對已有枚舉成員的引用,常量的表達式
常量枚舉成員會在編譯時計算出結果,然后以常量的形式,出現在運行時環境
 
(2)、需要計算的非常量表達式
這些枚舉成員的值不會在編譯階段計算,而是保留到程序的執行階段
enum Char {
  // 常量枚舉成員
  a,
  b = Char.a,
  c = 1 + 3,
  // 非常量枚舉成員
  d = Math.random(),
  e = 'hello'.length
}

console.log(Char);


// 編譯
var Char;
(function (Char) {
    // 常量枚舉成員
    Char[Char["a"] = 0] = "a";
    Char[Char["b"] = 0] = "b";
    Char[Char["c"] = 4] = "c";
    // 非常量枚舉成員
    Char[Char["d"] = Math.random()] = "d";
    Char[Char["e"] = 'hello'.length] = "e";
})(Char || (Char = {}));


// 運行
{ '0': 'b',
  '4': 'c',
  '5': 'e',
  a: 0,
  b: 0,
  c: 4,
  d: 0.5257674738591782,
  '0.5257674738591782': 'd',
  e: 5 }

 

(3)、出現在非常量表達式后面的枚舉成員必須要賦初始值,否則會報錯(如下例中的 成員f )
enum Char {
  // 常量枚舉成員
  a,
  b = Char.a,
  c = 1 + 3,
  // 非常量枚舉成員
  d = Math.random(),
  e = 'hello'.length,
  f // 枚舉成員必須具有初始化表達式
}

 

5、常量枚舉
常量枚舉是在 enum關鍵字前使用 const 修飾符
特點:在編譯階段被移除
作用:當我們不需要一個對象,而需要對象的值,就可以使用常量枚舉,這樣就可以避免在編譯時生成多余的代碼和間接引用
const enum Month {
  Jan,
  Feb,
  Mar
}

// 編譯時,沒有任何輸出

console.log(Month);  // "const" 枚舉僅可在屬性、索引訪問表達式、導入聲明的右側、導出分配或類型查詢中使用。

 

常量枚舉成員在使用的地方被內聯進來,且常量枚舉不可能有計算成員
const enum Directions {
  Up,
  Right,
  Down,
  Left
}

let directions = [Directions.Up, Directions.Right, Directions.Down, Directions.Left];

// 編譯
var directions = [0 /* Up */, 1 /* Right */, 2 /* Down */, 3 /* Left */];

console.log(directions);
[ 0, 1, 2, 3 ]
const enum Directions {
  Up,
  Right,
  Down,
  Left,
  UpRight = 3 + 1,
  RightDown = Directions.Right + 2,
  LeftDown = 9,
  // RightUp = 'hello'.length  // const enum member initializers can only contain literal values and other computed enum values
}

let directions = [
  Directions.Up, 
  Directions.Right, 
  Directions.Down, 
  Directions.Left, 
  Directions.UpRight,
  Directions.RightDown,
  Directions.LeftDown
];

// 編譯
var directions = [
    0 /* Up */,
    1 /* Right */,
    2 /* Down */,
    3 /* Left */,
    4 /* UpRight */,
    3 /* RightDown */,
    9 /* LeftDown */
];

console.log(directions);
[ 0, 1, 2, 3, 4, 3, 9 ]

 

6、在某些情況下,枚舉和枚舉成員都可以作為單獨的類型存在

enum E { a, b }
enum F { a = 0, b = 1 }
enum G { a = 'apple', b = 'banana' }

let e: E = 4;
let f: F = 4;
// console.log(e === f);  // This condition will always return 'false' since the types 'E' and 'F' have no overlap.

let e1: E.a = 3
let e2: E.b = 3
let e3: E.a = 3
// console.log(e1 === e2);  // This condition will always return 'false' since the types 'E.a' and 'E.b' have no overlap
console.log(e1 === e3);     // true

let g1: G = G.a
let g2: G.a = G.a
console.log(g1 === g2);     // true

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM