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

Javascript 为什么这里使用指数枚举键?,javascript,typescript,parsing,compilation,Javascript,Typescript,Parsing,Compilation,您可以找到以下代码: enum NodeFlags { None = 0, Let = 1, Const = 2, NestedNamespace = 4, Synthesized = 8, Namespace = 16, ExportContext = 32, ContainsThis = 64, 我在其他地方也见过这样的数值常量。这样做的目的是什么 我的猜测是,在现有项目之间添加一些新项目已经完成。特别是看到这个, T

您可以找到以下代码:

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,

请注意,此处可能是不正确的(因此我很抱歉,欢迎您更正)。

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

let x = NodeFlags.AwaitContext  | NodeFlags.ThisNodeHasError // The node is both an await context but also has errors
为此,值不得在位级别相互干扰,因此每个值必须是2的幂(对于每个幂,只有一个位在不同位置设置为1)

基本上,值中的每一位都是一个独立的标志。它们可以在节点上使用单独的标志,例如
island
isConst
isAwaitContext
isError
等,但这在内存和编译器方面都是浪费的,因为有很多节点。这样,64位的单个字段可以表示64个标志


要提取设置的值,可以使用
&
运算符,例如
x&NodeFlags.ThisNodeHaser!==0
意味着ThisNodeHaser错误设置在
x
变量中。

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

None = 0b0,
Let = 0b1,
Const = 0b10,
NestedNamespace = 0b100,
Synthesized = 0b1000,
Namespace = 0b10000,
等等。这使得可以组合标志,例如
111
means
Let、Const、NestedNamespace


在您的例子中,
ReachabilityCheckFlags=384
是二进制的
0b110000000
,因此它将标志与值
128
0b10000000
)和
256
0b100000000

结合在一起,您可以通过使用组合标志检查值来获得枚举类型

这也适用于另一个方向,您可以使用

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,containstThis:64},
块范围=3,
flagsOfBlockScoped=getFlags(blockScoped);

console.log(flagsOfBlockScoped)嗨,提香,好久不见了:-)对不起,我对按位运算有点笨,我猜这与它们有关,但按位运算对奇数(如3)有效吗?我只是不知道。@Nurbollypysbayev
3
是二进制的
11
,它将Let和Const的标志组合在一起。@Nurbollypysbayev它可以工作,但你必须在二进制中考虑一下。例如,
0001
is let
0010
is
const
如果按位计算,则得到
0011
即3,因此值3表示节点同时为let和const。@Nurbollypsbayev值中的每个位基本上都是一个独立的标志。它们可以在节点上使用标志,例如
island
isConst
isAwaitContext
isError
等,但这在内存和编译器方面都是浪费的,因为有很多节点。最好使用一个整型来表示所有这些(一个值最多64个标志)Titian,非常好的解释谢谢!其他人也很好,但是你是第一个回答的,而且解释很简单。你的解释让我觉得很有意思,所以任何键都是1或10或100或1000,前两个键加起来是11,在十进制中是3。“这太简单了!”Nurbolpysbayev第一个定义了所有的单个元素,而
3
组合了两个单个元素,形成了Let和Const的位掩码。您可以使用任何位掩码,但如果它包含多个二进制
1
数字,则表示它是一个组合。一般来说,这意味着它也不是二的幂(十进制)。谢谢你,弗拉兹。我对你的问题投了更高的票,但接受了另一个问题,因为它对我来说更简单。但是,你能解释一下为什么把
b
放在
1
s之前吗?我从来没有见过这种写二进制的方式,通常看起来是001,010,100etc@NurbolAlpysbayev哦,这就是二进制在JS中的作用。还有一些其他语言,但我使用的是JS符号。如果您在JS中键入
console.log(0b101)
,它将得到
5
打印。我想它会更清晰,因为如果你谈论
10
10
,一个是十进制的,另一个是二进制的,这会让人感到困惑。哈哈。我不知道,因为从来没有在JS(或其他地方)中使用过它。非常感谢你,让这一天对你有好处吧!:-)@努尔博拉皮斯巴耶夫我们都学到了,这就是为什么我们在这里,对吗?:)