Javascript:(ES5)数组迭代的权威指南

时间:2013-11-07 18:07:32

标签: javascript ecmascript-5

关于如何在Javascript中“正确”迭代数组有很多困惑。至少有两个帖子有几百个赞成票,但答案非常矛盾。我很困惑。

ES5添加了Array.prototype.forEach功能。这是最终答案还是仍有陷阱避免踩到?

如果有一个迭代,请发布真正的一次迭代。我可以使用ES5如果你不知道你在说什么,请不要发帖。

1 个答案:

答案 0 :(得分:2)

简单回答:如果你想避免令人不快的意外,就无法理解Javascript的对象模型,包括原型继承。 Javascript Arrays基本上是具有一些附加属性的对象,它们非常与其他任何流行语言中的Arrays不同。

Array.prototype.forEach以及jquery.each有一个更大的陷阱,而不仅仅是通常被建议反对的干净for (var k in a)。我没有看到任何其他帖子中提到的这个陷阱。

查找

Array.prototype[2] = 'hi';

var a = [];
a.forEach(alert); // nothing
alert(a);  // ''

a[3] = 3;
a.forEach(alert); // 'hi', then '3'
alert(a);  // ',,hi,1'

这里发生了什么?请参阅实施Array.prototype.forEach的{​​{3}}(在“兼容性”下)。

a.forEach(myCallback)或多或少等同于常见的

for (var p = 0, len = a.length; p < len; p++) {
    if (p in a)
        myCallback(a[p], p, a);
}

这意味着它也会循环原型链中的属性!但只是以不太可靠的方式,因为它只会循环满足p < len的属性。

100%可靠的方法:

以下版本仅迭代可枚举属性。可以使用Object.getOwnPropertyNames函数代替Object.keys来包含不可枚举的属性。

数字,拥有,顺序

a.forEach(function(v, k, a) {
    if (a.hasOwnProperty[k])
        myCallback(v, k, a);
});

拥有,顺序

Object.keys(a).sort(mySortFunc).forEach(function(k) {
    myCallback(a[k], k, a);
});

数字,顺序

alert("Don't do it");

<强>自己的

Object.keys(a).forEach(function(k) {
    myCallback(a[k], k, a);
});

(无约束)

for (var k in a) {
    myCallback(a[k], k, a);
}

我不认为最后一个这么糟糕的选择。这是一种非常诚实和简洁的迭代方式。作为旁注,连续数值迭代已被证明在大多数实现中具有性能优势,至少对于非稀疏数组而言;但也许这不是规范的错误。