面試官:TypeScript中普通枚舉的反向映射是什么,它與常理枚舉的區別
在 TypeScript 中,普通枚舉(非 const enum)的一個特點是它會生成反向映射。這意味著你不僅可以通過枚舉的名字獲取對應的數值,還可以通過數值反查到枚舉的名字。
舉個例子
假設我們有一個枚舉:
enum Color {
Red, // 0
Green, // 1
Blue // 2
}
在編譯后的 JavaScript 中,TypeScript 會生成類似下面的代碼:
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
這里發生了兩件事:
- 正向映射:通過枚舉名稱獲取數值。例如,
Color.Red
返回0
。 - 反向映射:通過數值獲取枚舉名稱。例如,
Color[0]
返回"Red"
。
反向映射的作用
反向映射的優勢在于你可以輕松地將數值轉換回它們對應的枚舉名稱,這在調試、日志記錄或者在某些業務場景中需要顯示友好的名稱時非常有用。
例如:
console.log(Color.Red); // 輸出 0
console.log(Color[0]); // 輸出 "Red"
總結
- 正向映射:
Color.Red
→0
- 反向映射:
Color[0]
→"Red"
這種雙向映射機制只適用于數字枚舉。如果是字符串枚舉,TypeScript 不會生成反向映射,因為反向映射對于字符串來說沒有意義。
與常量枚舉(const enum)區別
在 TypeScript 中,普通枚舉和常量枚舉(const enum)有以下主要區別:
1. 編譯后的輸出
- 普通枚舉:
編譯后會生成一個實際的對象,包含正向和反向映射。
例如:
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
這意味著你可以通過 Color.Red
得到 0
,也可以通過 Color[0]
得到 "Red"
。
- 常量枚舉(const enum):
編譯后不會生成實際的枚舉對象。
所有對常量枚舉成員的引用都直接被內聯替換成對應的值。例如:
const enum Color {
Red,
Green,
Blue
}
let c = Color.Green;
編譯后代碼會直接變成:
let c = 1;
沒有額外的對象和反向映射生成。
2. 反向映射
- 普通枚舉:
自動生成反向映射,使得可以通過值查找名稱(僅適用于數字枚舉)。 - 常量枚舉:
沒有反向映射,因為編譯器會直接將枚舉成員內聯,反向查找就沒有意義。
3. 用途與性能
- 普通枚舉:
如果需要在運行時使用枚舉對象(例如調試或反向查找),普通枚舉是合適的選擇。但生成的代碼體積稍大,因為需要創建完整的對象。 - 常量枚舉:
如果僅僅是為了在編譯時使用枚舉值,并且不需要運行時的對象或反向映射,可以使用常量枚舉。這樣可以減少編譯后的代碼體積和運行時開銷,因為枚舉成員會被內聯。
總結
- 普通枚舉生成實際的對象,支持雙向映射,適合需要運行時反向查找的場景。
- 常量枚舉在編譯后直接內聯枚舉值,沒有生成實際對象和反向映射,適合追求代碼體積優化且不需要運行時枚舉對象的場景。