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。此处的指数可能不正确(很抱歉,欢迎您纠正我)。
答案 0 :(得分:3)
原因是此枚举用作标记枚举。可以使用按位或(|
)运算符组合这些值。因此,您可以同时拥有枚举的两个成员
let x = NodeFlags.AwaitContext | NodeFlags.ThisNodeHasError // The node is both an await context but also has errors
要使其正常工作,这些值不能在位级别上相互干扰,因此每个值必须是2的幂(对于每个功率,在不同的位置,只有一个位设置为1)>
基本上,值中的每个位都是一个独立的标志。它们本来可以在节点上带有单独的标志,例如isLet
,isConst
,isAwaitContext
,isError
等,但是这在内存方面是浪费的,而且对于由于有许多节点,所以合计的编译器。这样,单个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 = 384
是0b110000000
的二进制文件,因此它将标志与值128
(0b10000000
)和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);