为什么在JavaScript中,双重查找比单次查找更快?

16

我在一个 jsperf 测试中发现了一些奇怪的行为。以下是设置:

var pro={};
pro._x=3;
var q=Object.create(pro);
q.x=3;
q.z={};
q.z.x=3;

然后,我只是查找每个属性q.xq._xq.z.x

单一查找q.x比原型查找q._x更快,这是预料中的。但是双重查找q.z.x是最快的。我原本以为q.z.x会是最慢的,特别是与q.x相比。

q.z.x甚至比q.z还要快。这里发生了什么?


19
编译器优化… - RobG
它类似于旧但经典的“volatile”优化。您会两次引用该变量,因此您将大量使用它(或者至少,优化器认为是这样)。 - Alex
在测试 http://jsperf.com/8dfns4/4 的第四个版本中,将 q.x=3 移到最后一行时,在 Firefox 37.0 中双重查找是最慢的。 - Leonidas Kapsokalivas
我曾认为q.<something>之所以更快,是因为它有多个兄弟节点,而q.<something>.<something>没有兄弟节点,因此在查找属性时,它需要迭代的项较少。但我错了,在将多个兄弟节点添加到对象根时,在Firefox中双重查找实际上具有相同的速度:http://jsperf.com/8dfns4/7 - Blaise
2
好奇的是,查找的顺序是否重要?比如在q.z.x之后或其他方式之后执行q.x会有什么不同吗? - Lex Podgorny
显示剩余4条评论
1个回答

1
更深入的查找速度更快的原因在于JavaScript引擎能够更好地优化代码以提高性能,因为它知道确切地接收了什么对象。与使用Object.create不同,引擎无法执行其正常的优化循环,使用一个普通的空对象来初始化q对象的z属性,基本上允许引擎分配适当的内存并相应地对其进行索引。这段代码"var q=Object.create(pro);"基本上告诉JS引擎:"嘿,你得到了一个对象的实例,但我不知道它是什么类型。可能是一个数组、对象、RegExp、日期。"而这段代码--"q.z={};"则表示--"嘿,你在这里得到了一个对象对象!请确保按照此数据类型留出一些内存。"

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