V8内部如何表示对象?

6
我曾经认为JavaScript中的对象只是简单的键值对,即哈希表,但在阅读这篇文章之后,我感到困惑。
作者特别提到:

当你使用一个对象就像它是一个哈希表时,它就会被转换成一个哈希表。

所以,在此之前它到底是什么?整段话让我感到困惑。有人可以解释一下吗?

这可能不是针对编程语言层面的。而是关于你如何使用语言。 - Pascal
2
没有时间给出完整的答案,但 JIT 可以将某些对象转换为代码,其中属性查找非常高效,几乎像 C 结构一样,并且它是 O(1)。除非它不能,否则它会使用真正的哈希表作为后备存储器。 - Alnitak
1个回答

10
根据这个答案,在V8中,一个对象可以有两种模式——字典模式和快速模式。
对象最初处于快速模式,在此模式下,访问属性时不需要哈希映射或计算。它像C语言中的结构体一样存储对象。只有当您开始像使用哈希表一样使用“对象”时,它才会被转换为哈希表——即进入字典模式。一旦这种情况发生,您就会遇到性能惩罚,因为哈希映射将用于在幕后访问属性。
例如:
// running node with `--allow-natives-syntax` flag

var obj = { a: true, b: false };
%HasFastProperties(obj); // true (Fast mode)
delete obj.a;
%HasFastProperties(obj); // false (Dictionary mode)

或:
var obj = { a: true, b: false };
%HasFastProperties(obj); // true (Fast mode)
// add lots of properties
for (var i = 0; i < 100; i++) {
    obj["prop" + i] = i;
}
%HasFastProperties(obj); // false (Dictionary mode)

它转换为字典模式的原因是出于性能优化考虑。在字典模式下添加/删除属性比快速模式更快,因此V8引擎会针对检测到的这种行为进行优化,以更改结构而不是属性访问 (在此处阅读更多信息)。


这个特定于某个JavaScript引擎吗? - svick
@svick 是的,我只回答问题中提到的引擎 - v8。其他引擎可能会在幕后以不同的方式处理这个问题,所以我不能确定。 - David Sherret
我很好奇为什么需要字典模式,如果我们可以使用快速模式? - CodeYogi
@CodeYogi:“[字典模式] 确实会使事情变慢,但如果 V8 在您不断改变对象形状时仍然尝试保持快速模式,那么速度将更慢。” - 点击此处 - David Sherret
@CodeYogi,只是为了增加混淆:快速模式与字典模式的区别仍然是一个巨大的简化。实际上,在V8中表示属性的方式有超过半打种不同的方法,虚拟机使用运行时分析和各种启发式方法来动态地在它们之间进行切换。JavaScript是一种设计良好的语言,你不能通过像那样跳过无数的障碍来使它变得更快(有时甚至不行)。 - Andreas Rossberg
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接