为什么将带有数组的“ for(列表中的可变项)”视为JavaScript中的不良做法?


78

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

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];
    ...
}

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


您不是在使用该循环来遍历项目,而是在键/属性名称/ indizes上进行遍历。
Bergi 2012年

5
维多利亚时代的大礼帽中的C编码人员也不了解养蜂家。但是请记住,它吐出的是键,而不是值。for(;;)格式更快,但是在99%的时间中,这确实没有关系。除非您从事大型项目或真正需要优化的工作,否则编码时间要比计算时间贵。
Shayne 2014年

Answers:


96

首先,对于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)

2
这就是罚款,只要你使用hasOwnProperty,但- for (var i in a) { if (a.hasOwnProperty(i)) console.log(i); }- > 1 2 3
贝尔巴托夫克里斯托夫

11
一个建议,over all properties改为over **enumerable** properties。在较新的javascript实现中,可以将enumerable属性设置为来定义属性false。这些属性和内置javascript对象的属性不会显示在中for...in
安迪E

4
@Dimitar:确实,尽管将其添加进去,但循环看起来不再像标准C样式的for循环那样简单。
Tim Down'2

1
无论如何-像这样循环数组的唯一合法原因是获取数组键(由于javscript中数组的性质而起作用)-任何其他原因,最好进行常规循环。
Dimitar Christoff


1

如果这样使用for / in,则item枚举字符串值“ 0”,“ 1”,...,而不是列表中的实际对象。因此,第一个代码段中的“项目”更像i第二个代码段中的“项目” ,而不是item。此外,在需要数字的位置会枚举字符串值。当您将属性归入列表时,您会遇到麻烦array.ID = "a123",因为它们也会被枚举。

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


1

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

仅出于这个原因,它就不能代替for (i=0; i<arr.length; i++)循环。

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

相关的现代浏览器支持它(Internet Explorer不计数,而是由Microsoft Edge代替)。如果您负担不起不支持旧版浏览器的费用,那么这可能是可行的方法。您可以查看前面链接的MDN页面末尾的便捷浏览器支持表,以查看实际允许的浏览器版本for ... of ...使用的。


我很高兴知道您关于IE的主张是真实可信的:)
CapelliC

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.