2012-11-21 47 views
6

我已经在几个地方看到,for-in循环比循环遍历数组的速度慢......虽然我知道在sizeof(type)块中向前移动与在场景后面迭代遍历对象的键,我仍然好奇,究竟是什么原因,它是如此之慢...为什么在JavaScript中输入缓慢?

它是否必须做一个反向哈希函数来获得密钥,并且该过程是什么慢?

+2

是的,我猜想得到所有的键是一个相对缓慢的过程相比......没有得到它们;)for ... in'必须首先查找键,而使用正常的'for'循环,你正在通过循环变量提供密钥。 –

+2

这是一个JSPerf测试,它显示'for ... in'的运行与'Object.keys()'(至少在Chrome中)几乎相同:http://jsperf.com/for-in- VS-键-VS-的。所以,获取钥匙和/或与此相关的一切都比较慢,并且从外部提供钥匙。但它也取决于实施,就像T.J.说。 –

回答

3

在任何特定引擎的情况下,真正的答案可能取决于该引擎的实现。 (如果有的话,差异的大小也会如此)。

但是,有不变量。例如,考虑:

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的情况下,发动机必须使用一种机制来跟踪哪些属性你已经遍历,哪些还没有,以及过滤掉不可枚举的属性。例如,幕后有一些迭代器对象(以及spec定义的方式,可能是临时数组)。

arr的情况下,它没有;您正在以一种非常简单而有效的方式在您的代码中处理这些问题。

每个循环的块内容是相同的:对象的属性查找。 (在后一种情况下,理论上也有一个数字到字符串的转换。)

所以我期望唯一的非实现特定的答案是:额外的开销。

1

for..each循环使用iterators and generators

迭代器是一个具有next()方法的对象。 Generator是包含yield()表达式的工厂函数。这两个构造比一个整数索引变量更复杂。

在典型for(var i = 0; i < arr.length; i++)循环,即在执行两个指令几乎所有迭代i++i < arr。这可以说比进行函数调用要快得多(next()yield())。

此外,循环初始化(var i = 0)也比用迭代器对象创建迭代器对象更快,或者调用生成器来创建迭代器。但是,它高度依赖于实现,JavaScript引擎的创建者尽其所能地加速这些常用语言功能。

我想说这种差异是如此的微不足道,以至于我可能会花时间优化代码的其他部分。语法的选择应该考虑代码的可读性和可维护性而不仅仅是性能,当性能增益如此之小以增加复杂性时。话虽如此,使用更有意义的语法,您和其他开发人员在您丰富和着名后维护您的代码! ;)