所以要跟进上一个问题;
由于使用属性的动态功能和使用
进行迭代for(var key in array)
我已经非常喜欢尝试枚举数组并按数字迭代。
仅仅.pushing元素和设置为属性的优点和缺点是什么?
除了明显的识别差异外。
答案 0 :(得分:7)
缩短:
从不在数组上使用for in
,它极其缓慢且容易失败。
好吧,虽然JavaScript中的Array
是Object
,但没有充分的理由使用for in
循环来迭代它。事实上,for in
上使用Array
反对有很多很好的理由。
虽然起初看起来似乎是一个不错的选择,但是要将某些速度与for in
结构的可读性进行交换,这会对性能产生主要影响。
for in
确实迭代了Array
的索引。但它也会遍历原型链。因此,必须使用hasOwnProperty
以确保过滤掉不需要的属性,并且如果在阵列上碰巧定义了任何其他属性,它们仍将通过此过滤器。
Array.prototype.bar = 1; // poisoning the Object.prototype, NEVER do this
var foo = [1, 2, 3];
for(var i in foo) {
console.log(i);
}
上述代码导致打印出“索引”0
,1
,2
和 bar
。
使用hasOwnProperty进行过滤
Array.prototype.bar = 1; // poisoning the Object.prototype, NEVER do this
var foo = [1, 2, 3];
foo.blub = 2;
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
以上代码结果现在打印“索引”0
,1
,2
和 blub
,您无法过滤掉{ {1}}以任何有意义的方式,除非您验证密钥是正整数。
效果
现在,将遍历blub
的原型的慢速特性与for in
结合起来会导致性能下降,直至 20x 。
因此,如果你想在JavaScript中迭代hasOwnProperty
,总是使用经典的Array
循环结构。
for
正如您所看到的,上面的示例中还有一个额外的问题。这是通过var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}
缓存长度。
虽然在数组本身上定义了l = list.length
属性,但在每次迭代中进行查找仍然存在开销。虽然最近的JavaScript引擎可能在这种情况下应用优化,但是人们永远无法确定这些优化是否真正到位,也无法确定它们是否达到了上述缓存的速度。事实上,省略缓存可能会导致性能下降,直至 2x (在旧引擎中甚至更多)。
答案 1 :(得分:3)
最重要的区别是枚举将列出所有属性,甚至是原型链中的属性。例如(这并不罕见):
Array.prototype.isEmpty = function() {
return this.length == 0;
}
var myArray = [2, 3, 5];
for(var key in myArray) {
console.log(key);
}
将列出
0
1
2
isEmpty
isEmpty
很可能不是你想要的那个枚举。
此外,length
属性仅受数字索引的影响。在这种情况下,它不相关,因为您要枚举元素,但要记住一些事项。
var a = [];
a["4"] = "test";
a.length; // 5
a[10] = "ing";
a.length = 11;