我在几个地方读到 for-in 循环比遍历数组要慢......虽然我知道与在幕后发生的任何事情相比,在 sizeof (type) 块中前进实际上是毫不费力的,以迭代对象的键,我还是很好奇,到底是什么原因,这么慢……
是否必须执行反向哈希函数来获取密钥,而这个过程很慢?
我在几个地方读到 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
循环使用迭代器和生成器。
迭代器是一个有next()
方法的对象。生成器是一个包含yield()
表达式的工厂函数。这两种结构都比整数索引变量更复杂。
在一个典型的for(var i = 0; i < arr.length; i++)
循环中,几乎在所有迭代中执行的两个命令是i++
和i < arr
。这可以说比进行函数调用(next()
或yield()
)要快得多。
而且,循环初始化(var i = 0
)也比使用next()
方法创建迭代器对象或调用生成器创建迭代器要快。但是,它高度依赖于实现,Javascript 引擎的创建者尽最大努力加速这些常用的语言特性。
我会说差异是如此微不足道,以至于我可能想花时间优化代码的其他部分。语法的选择应该比性能更考虑代码的可读性和可维护性,因为性能增益对于增加复杂性来说是如此之小。话虽如此,请使用对您和其他在您变得富有和成名后维护您的代码的开发人员更有意义的语法!;)