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

Javascript: (ES5) Definitive guide to array iteration

本文关键字:迭代 数组 ES5 Javascript      更新时间:2023-09-26

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

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

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

简单的答案:如果你想避免不愉快的意外,就没有办法理解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'

这是怎么回事?请参阅 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);
}

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