在看 TypeScript Deep Dive,里面介绍一个 enum 定义成位运算的操作感觉非常简洁清晰

相关链接:
https://basarat.gitbook.io/typescript/type-system/enums#number-enums-as-flags

enum AnimalFlags {
    None           = 0,
    HasClaws       = 1 << 0,
    CanFly         = 1 << 1,
    EatsFish       = 1 << 2,
    Endangered     = 1 << 3
}

然后可以用 & 运算作判断和整合,类似掩码的思路

type Animal = {
    flags: AnimalFlags
}

function printAnimalAbilities(animal: Animal) {
    var animalFlags = animal.flags;
    if (animalFlags & AnimalFlags.HasClaws) {
        console.log('animal has claws');
    }
    if (animalFlags & AnimalFlags.CanFly) {
        console.log('animal can fly');
    }
    if (animalFlags == AnimalFlags.None) {
        console.log('nothing');
    }
}

我要泼个冷水,这个操作其实跟变量枚举没差别

const Foo = 1;
const Bar = 1 << 1;
const Baz = 1 << 2;

type Flag = typeof Foo | typeof Bar | typeof Baz;
var flag: Flag;

if (flag & Foo) {}
if (flag & Bar) {}
if (flag & Baz) {}

区别仅在于多了一个类型命名空间。

不用位运算就因为可读性不好,直接使用常量枚举反而更清晰

const enum Flag {
  Foo,
  Bar,
  Baz,
}

var flag: Flag;

switch (flag) {
  case Flag.Foo: {}
  case Flag.Bar: {}
  case Flag.Baz: {}
}

不需要关心枚举值,除非你真的需要它参与运算,这个时候就回到为什么不用位运算的问题了。

二进制位枚举有用的情况是 bitset 的场景,比如一篇文章只有一个审核状态,审核原因就可以用标志位来记录,比如指令置顶为 2 ,涉黄暴为 4 ,涉一号为 8 。但这种 bitset 的场景在 ts 里也不那么推荐, js 只有 53 位这种烂理由就不说了,重点是前端业务没有极致优化存储空间的需求,业务系统应该将不同标志位分开为不同的 boolean 状态字段,换取维护便利性。

    hsxfjames 重点是前端业务没有极致优化存储空间的需求,业务系统应该将不同标志位分开为不同的 boolean 状态字段,换取维护便利性。

    很有道理!难怪我们平时也没有这么用。

    这里我想到一个场景是 AssemblyScript,写嵌入式代码可能有用。

    © 2018-2025 0xFFFF