我在几个地方读到for in循环比在数组上循环慢。。。尽管我知道,与在后台迭代对象的键相比,在sizeof(type)块中向前移动实际上是毫不费力的,但我仍然很好奇,它如此缓慢的确切原因是什么。。。
是不是必须执行反向哈希函数才能获得密钥,而这个过程很慢?
在任何特定引擎的情况下,真正的答案可能取决于该引擎的实现。(差异的大小也是如此,如果有的话。)
然而,也存在不变量。例如,考虑:
var obj = {a: "alpha", b: "beta"};
var name;
for (name in obj) {
console.log(obj[name]);
}
var arr = ["alpha", "beta"];
var index;
for (index = 0; index < arr.length; ++index) {
console.log(arr[index]);
}
在obj
的情况下,引擎必须使用一种机制来跟踪哪些属性已经迭代,哪些属性还没有迭代,以及过滤掉不可枚举的属性。例如,在后台有某种迭代器对象(按照规范的定义方式,它很可能是一个临时数组)。
在arr
的情况下,它没有;您正在以一种非常简单、高效的方式在代码中处理它。
每个循环的块的内容都是相同的:对象上的特性查找。(在后一种情况下,理论上,还有数字到字符串的转换。)
因此,我认为唯一非实现特定的答案是:额外的开销。
for..each
循环使用迭代器和生成器。
Iterator是一个具有next()
方法的对象。Generator是一个包含yield()
表达式的工厂函数。这两个构造都比整数索引变量更复杂。
在典型的for(var i = 0; i < arr.length; i++)
循环中,在几乎所有迭代中执行的两个命令是i++
和i < arr
。这可以说比调用函数(next()
或yield()
)快得多。
此外,循环初始化(var i = 0
)也比用next()
方法创建迭代器对象或调用生成器创建迭代程序更快。然而,这在很大程度上取决于实现,Javascript引擎的创建者会尽最大努力加速这些常用的语言功能。
我想说,差异是如此之小,以至于我可能想把时间花在优化代码的其他部分上。语法的选择应该考虑代码的可读性和可维护性,而不是性能,因为性能增益对于增加复杂性来说非常小。话虽如此,请使用对您和其他在您变得富有和出名后维护您的代码的开发人员更有意义的语法!)