为什么在 JavaScript 中使用数组的“for(var item in list)”被认为是不好的做法?

IT技术 javascript arrays loops
2021-03-03 06:08:10

给定一个简单的基于零的数字索引数组:

var list = ['Foo', 'Bar', 'Baz'];

很多时候,我注意到当有人建议像这样循环遍历数组中的变量时:

for(var item in list) { ... }

...几乎可以肯定有人建议这是不好的做法并建议另一种方法:

var count = list.length;

for(var i = 0; i < count; i++) {
    var item = list[i];
    ...
}

不使用上面更简单的版本而是使用第二个示例的原因是什么?

5个回答

首先,循环的顺序对于循环是未定义的for...in,因此不能保证属性会按照您想要的顺序进行迭代。

其次,for...in迭代对象的所有可枚举属性,包括从其原型继承的属性。在数组的情况下,如果您的代码或页面中包含的任何库增加了 的原型,这可能会影响您Array,这可能是一件真正有用的事情:

Array.prototype.remove = function(val) {
    // Irrelevant implementation details
};

var a = ["a", "b", "c"];

for (var i in a) {
    console.log(i);
}

// Logs 0, 1, 2, "remove" (though not necessarily in that order)
@Dimitar:确实,虽然一旦你添加了它,循环就不再看起来比标准 C 风格的 for 循环更简单了。
2021-04-20 06:08:10
一个建议,over all properties改为over **enumerable** properties. 在较新的 javascript 实现中,可以使用enumerable设置为属性来定义属性false内置 javascript 对象的这些属性和属性不会显示在for...in.
2021-04-22 06:08:10
无论如何 - 像这样循环数组的唯一合法原因是获取数组键(由于 javscript 中数组的性质而起作用) - 任何其他原因,你最好做一个正常的循环。
2021-04-23 06:08:10
没关系,只要你使用hasOwnProperty- for (var i in a) { if (a.hasOwnProperty(i)) console.log(i); }-> 1 2 3
2021-04-29 06:08:10

速度?

for(..;..;..)事实证明,循环比我在这里测试时快 36 倍for .. in

链接礼貌这个 SO 答案

我误读了无限循环比普通循环快 36 倍。感谢您的链接 +1。
2021-04-25 06:08:10
@Thomas 合理的误解 - 脱离上下文阅读时。固定的 :)
2021-05-03 06:08:10

for ... in ... 不返回列表项,而是枚举数组属性。

仅因为这个原因,它不能作为for (i=0; i<arr.length; i++)循环的替代品

合适的替代方法是for ... of ...构建。它枚举可迭代对象的值,例如数组。您可以在 MDN Web Docs 上阅读更多相关信息:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

相关的现代浏览器都支持它(Internet Explorer 不算数,它被 Microsoft Edge 取代)。如果您负担不起不支持旧浏览器的费用,那么这可能是您要走的路。您可以查看前面链接的 MDN 页面末尾的便捷浏览器支持表,以查看实际允许for ... of ...使用哪些浏览器版本

我会很高兴知道你关于 IE 的断言可能是真实的和值得信赖的 :)
2021-04-20 06:08:10

如果像这样使用 for/in,则item枚举字符串值“0”、“1”……,因此不是列表中的实际对象。所以第一个片段中的“项目”更像i是第二个片段中的,而不是item. 此外,在您期望数字的地方枚举字符串值。当您将属性添加到列表中时,您会遇到麻烦,例如array.ID = "a123",因为它们也会被枚举。

但是有这些缺点,我仍然认为语法非常有用,如果你的团队知道它的作用。

添加list.foo = bar;并尝试使用简单的for. 如果您不使用某些库(如prototypeJs)并且不向数组对象添加任何新属性 - 您可以使用简单的 for 语句。