Logo
Section 1 / 4

带值与不带值的枚举

在本节课中,你将学习如何使用带有显式值和隐式值的枚举。

导入

带值与不带值的枚举

在本节课中,你将学习如何使用带有显式值和隐式值的枚举。

enum 的作用

enum 是一种结构,用于为变量定义一组允许的值。它通过指定具体的可选取值来约束变量的取值范围。

带值的 enum

enum 可以是 string 类型。在这种情况下,每个成员都必须显式赋值,不能例外。

1enum MyStringEnum { 2 ChoiceA = "A", 3 ChoiceB = "B", 4}

如果每个成员都有定义,允许混合使用不同类型的值(例如部分为数字,部分为字符串)。虽然语法上允许,但不建议混合类型,因为这可能使代码更难理解。

1enum MyStringAndNumberEnum { 2 ChoiceA, // 0 3 ChoiceB = "B", 4 ChoiceC = 100 5}

不带值的 enum

enum 是一种类型,用于强制限定一组固定的常量值。enum 必须有名称和可接受的值。之后,可以将 enum 用作类型。使用者必须通过 enum 名称加点号再加定义列表中的某个值来使用。

1enum MyEnum { 2 ChoiceA, 3 ChoiceB, 4 ChoiceC, 5} 6let x: MyEnum = MyEnum.ChoiceA; 7console.log(x);

默认情况下,成员值从 0 开始,依次递增。这种 enum 具有隐式值。开发者也可以显式指定某个值,此时 enum 为显式值。

1enum MyEnum { 2 ChoiceA, 3 ChoiceB, 4 ChoiceC, 5} 6enum MyEnum2 { 7 ChoiceA, // 0 8 ChoiceB = 100, // 100 9 ChoiceC, // 101 10 ChoiceD = MyEnum.ChoiceC, // 2 11} 12console.log(MyEnum2.ChoiceA); 13console.log(MyEnum2.ChoiceB); 14console.log(MyEnum2.ChoiceC); 15console.log(MyEnum2.ChoiceD);

enum 成员的值可以是直接赋值,也可以通过计算获得。计算分为两种类型:

  1. 常量计算
  2. 纯计算

常量计算是指由另一个 enum 提供的值,或通过加、减、位运算、取模、乘、除、“或”、“与”、“异或”操作符,以及按位取反操作符(~)计算得出的值。纯计算则来自一个函数。

enum 在 JavaScript 中会生成一个函数,其内部包含一个映射集合,可用于通过名称或数值访问对应的值。以下是之前两个 enum 在编译后的 JavaScript 输出:

1/* 2enum MyEnum { 3 ChoiceA, 4 ChoiceB, 5 ChoiceC, 6} */ 7// 编译后: 8 9var MyEnum; 10(function (MyEnum) { 11 MyEnum[MyEnum["ChoiceA"] = 0] = "ChoiceA"; 12 MyEnum[MyEnum["ChoiceB"] = 1] = "ChoiceB"; 13 MyEnum[MyEnum["ChoiceC"] = 2] = "ChoiceC"; 14})(MyEnum || (MyEnum = {})); 15 16/* 17enum MyEnum2 { 18 ChoiceA, // 0 19 ChoiceB = 100, // 100 20 ChoiceC, // 101 21 ChoiceD = MyEnum.ChoiceC, // 2 22} 23*/ 24 25// 在 JavaScript 中: 26var MyEnum2; 27(function (MyEnum2) { 28 MyEnum2[MyEnum2["ChoiceA"] = 0] = "ChoiceA"; 29 MyEnum2[MyEnum2["ChoiceB"] = 100] = "ChoiceB"; 30 MyEnum2[MyEnum2["ChoiceC"] = 101] = "ChoiceC"; 31 MyEnum2[MyEnum2["ChoiceD"] = 2] = "ChoiceD"; 32})(MyEnum2 || (MyEnum2 = {}));

使用位运算的 enum

enum 非常适合进行位运算,因为其值可以显式设置(在定义时指定),并且可以使用左移操作符(<<)。定义后,可以像普通变量一样使用它,判断是否包含某项功能,或使用按位与(&)检查某项是否存在。按位或(|)可用于将多个 enum 选项组合到一个变量中。

以下代码不仅使用 | 初始化值,还进行了值的检查。由于位运算返回的是数值而非布尔值,因此不能直接使用等号比较。需要将结果与目标值进行比较。第 10 行展示了如何检查 enum 的值。

1enum Power { 2 None = 0, // 十进制 0(二进制 00) 3 Invincibility = 1 << 0, // 十进制 1(二进制 01) 4 Telepathy = 1 << 1, // 十进制 2(二进制 10) 5 Invisibility = 1 << 2, // 十进制 4(二进制 100) 6 Everything = Invincibility | Telepathy | Invisibility, 7} 8let power: Power = Power.Invincibility | Power.Telepathy; 9console.log("Power values:" + power); 10if (Power.Telepathy === (power & Power.Telepathy)) { 11 console.log("Power of telepathy available"); 12}

前例中的值为 3,因为 Invincibility 的值是 1<<0,即二进制 01。
Telepathy 的值是 1<<1,即二进制 10。
按位或(|)操作的结果是二进制 11,即十进制 3。

可以通过 &= ~ 操作在运行时动态移除某个位值,该操作执行的是“与”运算,并对要移除的值取反。

例如,以下代码在前例基础上移除了 Telepathy 能力。第 13 行执行了移除操作。

1enum Power { 2 None = 0, // 十进制 0(二进制 00) 3 Invincibility = 1 << 0, // 十进制 1(二进制 01) 4 Telepathy = 1 << 1, // 十进制 2(二进制 10) 5 Invisibility = 1 << 2, // 十进制 4(二进制 100) 6 Everything = Invincibility | Telepathy | Invisibility, 7} 8let power: Power = Power.Invincibility | Power.Telepathy; 9console.log("Power values:" + power); 10if (Power.Telepathy === (power & Power.Telepathy)) { 11 console.log("Power of telepathy available"); 12} 13power &= ~Power.Telepathy; 14console.log("Power values:" + power); 15if (Power.Telepathy === (power & Power.Telepathy)) { 16 console.log("Power of telepathy available"); 17}

结果为 1,因为从 3(二进制 11)中与 10 的反码 01 进行按位与运算:11 & 01 = 01,即十进制 1。

动态添加值时,同样使用 | 操作符,如同初始化时一样。第 18 行显示,不仅可以使用 Power.Everything 设置所有值,还可以直接使用表示二进制值的数字。例如,7(二进制 0b111)将前三个能力设为开启状态。

1enum Power { 2 None = 0, 3 Invincibility = 1 << 0, 4 Telepathy = 1 << 1, 5 Invisibility = 1 << 2, 6 Everything = Invincibility | Telepathy | Invisibility, 7} 8let power: Power = Power.Invincibility | Power.Telepathy; 9console.log("Power values:" + power); 10if (Power.Telepathy === (power & Power.Telepathy)) { 11 console.log("Power of telepathy available"); 12} 13power &= ~Power.Telepathy; 14console.log("Power values:" + power); 15if (Power.Telepathy === (power & Power.Telepathy)) { 16 console.log("Power of telepathy available"); 17} 18power |= 7; // 7 是二进制 0b111 19console.log("Power values:" + power); 20if (power === Power.Everything) { 21 console.log("Everything"); 22}

现在我们已经了解了 enum 的两种类型,接下来学习如何访问 enum 的值。

注释

访问枚举值