为什么在这里使用指数枚举键?

时间:2019-03-14 12:33:11

标签: javascript typescript parsing compilation

Here,您可以找到以下代码:

enum NodeFlags {
    None = 0,
    Let = 1,
    Const = 2,
    NestedNamespace = 4,
    Synthesized = 8,
    Namespace = 16,
    ExportContext = 32,
    ContainsThis = 64,

我在其他地方也看到过这样的数字常量。这样做的目的是什么?

我的猜测是,以后在现有项目之间添加一些新项目已经完成了。尤其是在看到以下内容之后:

    ThisNodeHasError = 32768,
    JavaScriptFile = 65536,
    ThisNodeOrAnySubNodesHasError = 131072,
    HasAggregatedChildData = 262144,
    JSDoc = 1048576,
    BlockScoped = 3, // three?

但是在这种情况下,拥有100、200、300等数字不是更容易吗?

另一个猜测是它与按位运算有关,但是我在看到3之后根本不确定。

FWIW,该列表完全怪异地结束了:

    ReachabilityCheckFlags = 384,
    ReachabilityAndEmitFlags = 1408,
    ContextFlags = 6387712,
    TypeExcludesFlags = 20480,

P.S。此处的指数可能不正确(很抱歉,欢迎您纠正我)。

3 个答案:

答案 0 :(得分:3)

原因是此枚举用作标记枚举。可以使用按位或(|)运算符组合这些值。因此,您可以同时拥有枚举的两个成员

let x = NodeFlags.AwaitContext  | NodeFlags.ThisNodeHasError // The node is both an await context but also has errors

要使其正常工作,这些值不能在位级别上相互干扰,因此每个值必须是2的幂(对于每个功率,在不同的位置,只有一个位设置为1)

基本上,值中的每个位都是一个独立的标志。它们本来可以在节点上带有单独的标志,例如isLetisConstisAwaitContextisError等,但是这在内存方面是浪费的,而且对于由于有许多节点,所以合计的编译器。这样,单个64位字段可以表示64个标志。

要提取设置的值,可以使用&运算符,例如x & NodeFlags.ThisNodeHasError !== 0表示将在x变量中设置ThisNodeHasError。

答案 1 :(得分:2)

这些都是2的幂,因此在二进制中,您将拥有

None = 0b0,
Let = 0b1,
Const = 0b10,
NestedNamespace = 0b100,
Synthesized = 0b1000,
Namespace = 0b10000,

以此类推。这样就可以合并标志,例如111意味着Let, Const, NestedNamespace

在您的情况下,ReachabilityCheckFlags = 3840b110000000的二进制文件,因此它将标志与值1280b10000000)和256({{1} })

答案 2 :(得分:2)

使用组合标志,可以通过使用bitwise AND &检查值来获取枚举类型。

这在另一个方向上也可以工作,您可以只用bitwise OR |添加所有标志

const getFlags = value => Object.keys(nodeFlags).filter(k => nodeFlags[k] & value);

var nodeFlags = { None: 0, Let: 1, Const: 2, NestedNamespace: 4, Synthesized: 8, Namespace: 16, ExportContext: 32, ContainsThis: 64 },
    blockScoped = 3,
    flagsOfBlockScoped = getFlags(blockScoped);
    
console.log(flagsOfBlockScoped);