2

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

ES5 添加了Array.prototype.forEach功能。这是最终的答案,还是还有避免介入的陷阱?

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

4

1 回答 1

1

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

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'

这里发生了什么事?请参阅MDN (在“兼容性”下)实现的规范兼容算法Array.prototype.forEach

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);
}

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

于 2013-11-07T18:07:31.687 回答