我知道 V8 字节码“LdaUndefined”将常量“undefined”加载到累加器寄存器中。
那么“LdaTheHole”将什么加载到蓄能器中?
也许是“洞”?
“TheHole”是什么意思?
谢谢你。
最佳答案
(这里是 V8 开发人员。)
what does "LdaTheHole" load into the accumulator? Maybe "TheHole"?
是的。
What is the meaning of the "TheHole"?
正如马克的回答正确猜测的那样,它是一个内部哨兵,意思是“这里没有值(value)”。但是,需要它的原因不是性能(或分配);在某些情况下需要获得正确的行为。
对于基于数组的示例,请考虑以下代码:
var a = [1, 2, 3]; // (1)
a.__proto__ = [11, 22, 33]; // (2)
delete a[1]; // (3)
console.log(a[1]); // (4)
这将打印
22
, 因为 a
概念上将在索引 [1]
处有一个“洞” ,你可以“通过那个洞看到它的原型(prototype)”,可以这么说。 (如果将第 (1) 行和第 (3) 行替换为 var a = [1, , 3]
,您可以创建相同的情况。)如果 a
有默认原型(prototype),然后代替 delete a[1]
你可以写a[1] = undefined
, 或者这就是 delete
可以在引擎盖下做,结果是一样的。但是对于自定义原型(prototype),情况有所不同:如果您写了 a[1] = undefined
代替第 (3) 行,然后第 (4) 行将打印 undefined
.我们需要“洞”哨兵来区分元素 [1]
是 undefined
或根本不存在。在其他一些情况下,区分“无值”和“定义为‘未定义’”是有用或必要的,例如对于 block 范围变量的“时间死区”。旧式
var
-variables 隐式提升其声明,而访问新式 let
- 定义之前的变量是错误的。正确的行为是:
var a = 1; print(a); // 1
let b = 1; print(b); // 1
print(c); var c = 1; // undefined
print(d); let d = 1; // ReferenceError: Cannot access 'd' before initialization
print(e); // ReferenceError: e is not defined
所以
print
语句(这只是一个示例;许多其他操作也是如此)必须根据周围的代码做三件不同的事情。 V8 通过在内部将这些行转换为:let c = undefined; print(c); c = 1;
let d = <TheHole>; print(d); d = 1;
这样,当被访问的变量的值是“洞”时,系统就知道出了问题,所以在这种情况下,而不是加载变量的值并将其传递给
print
函数,它知道 this 必须是在其定义之前被访问的 block 范围变量,因此它会产生适当的错误消息。如果您想玩这些东西,请注意“洞”纯粹是内部哨兵。它永远不会“泄露”给 JavaScript。无法从您的代码中检查变量或属性当前是否具有此值。这是一个隐藏的实现细节——引擎可以做不同的事情;碰巧有一个内部“洞”哨兵是解决一堆问题的一种相当优雅和有效的方法,所以 V8 选择这样做。
关于javascript - 谁能解释 V8 字节码 LdaTheHole?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61420580/