关于如何在Javascript中“正确”迭代数组有很多困惑。至少有两个帖子有几百个赞成票,但答案非常矛盾。我很困惑。
ES5添加了Array.prototype.forEach
功能。这是最终答案还是仍有陷阱避免踩到?
如果有一个迭代,请发布真正的一次迭代。我可以使用ES5如果你不知道你在说什么,请不要发帖。
答案 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
的属性。
以下版本仅迭代可枚举属性。可以使用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);
}
我不认为最后一个这么糟糕的选择。这是一种非常诚实和简洁的迭代方式。作为旁注,连续数值迭代已被证明在大多数实现中具有性能优势,至少对于非稀疏数组而言;但也许这不是规范的错误。