Javascript JS性能:为什么不';t加载未初始化或已删除的元素

Javascript JS性能:为什么不';t加载未初始化或已删除的元素,javascript,v8,Javascript,V8,报告说: 不要加载未初始化或已删除的元素。并给出以下例子 //示例1 a=新数组(); 对于(var b=0;b

报告说:

不要加载未初始化或已删除的元素。并给出以下例子

//示例1
a=新数组();
对于(var b=0;b<10;b++){
a[0]|=b;//哦,不!
}
//例2
a=新数组();
a[0]=0;
对于(var b=0;b<10;b++){
a[0]|=b;//好多了!快了两倍。
}
现在我想知道为什么仅仅是未初始化的数组的第一个元素就可以导致巨大的性能差异。我认为在循环中第一次分配
a[0]
之后,这两个示例应该执行相同的操作。因此,它所需的时间应该与它们运行的时间几乎相同


谢谢你的回答。

我想重点是,在第二个例子中,
a
的0索引值不是
未定义的
——因为你已经为该索引分配了一个值,现在当对其进行评估时,它是根据已建立/已实现的索引+值进行评估的


这可能完全正确,也可能不完全正确,但这就是要点。您也可以始终在jsperf.com上创建一个条目并测试这一理论

第一个数组以字典或非类型对象数组(可以保存未定义的
)开始,并且在转换为数组之前可能会保持字典的状态一段时间,这是非常昂贵的

第二个数组可以从一开始就由整数数组支持,整数数组是一种非常快速的结构


请注意,这些优化可能会发生更改,因此当您阅读此答案时,引擎的工作方式可能不同。

a
在两个代码示例中都声明为空数组。在两个代码示例中都不必将其转换为数组。@jfriend00内部V8使用不同类型的数组。例如,当您可以将任何值作为键或值传递时,可以使用字典。还有一个紧凑的整数数组,当您只传递小的连续整数作为键,只传递32位整数作为值(这可能是数组最快的内部存储类型)。所有数组都支持JS对象功能(不确定为什么称它为字典,因为它不是JS类型)。您可以向任何数组添加任意属性。@jfriend00我们说的是V8选择的存储实现。V8定义的内部类型多于指定的类型。我编辑我的答案是为了更清晰。我看不出对你的答案的任何编辑实际上是为了澄清这一点。这变得越来越奇怪。请参阅此jsperf,它在Chrome中没有任何逻辑意义:。它在Firefox和IE11中工作正常(两种情况下速度相同)。@jfriend00第一个可以立即由整数数组支持,而第二个不能。不是假装我确信这是V8当前版本的真实情况,但这种推理通常会带来更好的性能。@dystroy-你是在评论我的jsperf中的两个案例还是OP的代码?我的两个案例都有一个用一个或多个整数初始化的数组。@jfriend00在测试案例中,我看到我们有
[0]
(一个整数数组),然后是
[]
(一个非类型数组)。@dystroy-而且,我的JSFIDLE
[0]
(您正在调用的整数数组)中的第一个在Chrome中要慢得多。这就是奇怪的地方。整数数组是否比Chrome的内部非类型数组慢很多?
// example1
a = new Array();
for (var b = 0; b < 10; b++) {
  a[0] |= b;  // Oh no!
}

// example2
a = new Array();
a[0] = 0;
for (var b = 0; b < 10; b++) {
  a[0] |= b;  // Much better! 2x faster.
}