JavaScript for…in vs for

您是否认为for ... in和for循环有很大的不同?您更喜欢使用哪种“用于”,为什么?

假设我们有一个关联数组的数组:

var myArray = [{'key': 'value'}, {'key': 'value1'}];

这样我们就可以迭代:

for (var i = 0; i < myArray.length; i++)

和:

for (var i in myArray)

我没什么大不同。有性能问题吗?

梅猿2020/03/13 16:47:04

for in语句允许遍历对象的所有属性的名称。不幸的是,它还会遍历通过原型链继承的所有成员。当关注数据成员时,这不利于提供方法功能。

Tom阳光达蒙2020/03/13 16:47:04

两者之间有重要区别。for-in遍历对象的属性,因此当case是数组时,它将不仅遍历其元素,而且遍历其具有的“ remove”功能。

for (var i = 0; i < myArray.length; i++) { 
    console.log(i) 
}

//Output
0
1

for (var i in myArray) { 
    console.log(i) 
} 

// Output
0 
1 
remove

您可以将for-in与一起使用if(myArray.hasOwnProperty(i))尽管如此,当遍历数组时,我总是更喜欢避免这种情况,而只使用for(;;)语句。

西里伽罗2020/03/13 16:47:04

尽管它们都非常相似,但还是有细微的差别:

var array = ["a", "b", "c"];
array["abc"] = 123;
console.log("Standard for loop:");
for (var index = 0; index < array.length; index++)
{
  console.log(" array[" + index + "] = " + array[index]); //Standard for loop
}

在这种情况下,输出为:

循环标准:

数组[0] = A

阵列[1] = B

数组[2] = C

console.log("For-in loop:");
for (var key in array)
{
  console.log(" array[" + key + "] = " + array[key]); //For-in loop output
}

而在这种情况下,输出为:

转入圈:

阵列[1] = B

数组[2] = C

阵列[10] = D

数组[ABC] = 123

Jim老丝L2020/03/13 16:47:04

使用Array()。forEach循环利用并行性

西里凯2020/03/13 16:47:04

根据jsperf,较短和最佳的代码是

keys  = Object.keys(obj);
for (var i = keys.length; i--;){
   value = obj[keys[i]];// or other action
}
米亚番长2020/03/13 16:47:04

for(;;)用于数组:[20,55,33]

for..in对象:{x:20,y:55:z:33}

西门LEY2020/03/13 16:47:04

我已经看到使用对象,原型和数组的“ for each”问题

我的理解是for for是对象的属性,而不是数组的属性

卡卡西猿2020/03/13 16:47:04

如果您真的想加速代码,那该怎么办?

for( var i=0,j=null; j=array[i++]; foo(j) );

这有点在for语句中包含while逻辑,并且冗余程度较低。Firefox也具有Array.forEach和Array.filter

Stafan猴子2020/03/13 16:47:04

数组上的for in循环与Prototype不兼容。如果您认为将来可能需要使用该库,则最好坚持使用for循环。

http://www.prototypejs.org/api/array

前端猴子2020/03/13 16:47:04

小心!

例如,如果您有多个脚本标签,并且正在标签属性中搜索信息,则必须将.length属性与for循环一起使用,因为它不是一个简单的数组,而是一个HTMLCollection对象。

https://developer.mozilla.org/en/DOM/HTMLCollection

如果将foreach语句用于(list中的var i),它将在大多数浏览器中返回HTMLCollection的属性和方法!

var scriptTags = document.getElementsByTagName("script");

for(var i = 0; i < scriptTags.length; i++)
alert(i); // Will print all your elements index (you can get src attribute value using scriptTags[i].attributes[0].value)

for(var i in scriptTags)
alert(i); // Will print "length", "item" and "namedItem" in addition to your elements!

即使getElementsByTagName应该返回NodeList,大多数浏览器也会返回HTMLCollection:https : //developer.mozilla.org/en/DOM/document.getElementsByTagName

樱Harry2020/03/13 16:47:04

我会根据想要引用项目的方式使用不同的方法。

如果只需要当前项目,请使用foreach。

如果需要索引器进行相对比较,则用于。(即与上一个/下一个项目相比如何?)

我从未注意到性能差异。我会等到出现性能问题后再担心它。

斯丁Green2020/03/13 16:47:04

使用for(myArray中的var i),您也可以循环对象,将包含键名,并且可以通过myArray [i]访问该属性另外,您将添加到对象中的任何方法也将包含在循环中,即,如果您使用任何外部框架(如jQuery或原型),或者如果直接将方法添加到对象原型,则将指向这些方法。

逆天前端2020/03/13 16:47:04

使用forEach跳过原型链

只是上述@nailer答案的快速附录,将forEach与Object.keys一起使用意味着您可以避免在原型链上进行迭代,而不必使用hasOwnProperty。

var Base = function () {
    this.coming = "hey";
};

var Sub = function () {
    this.leaving = "bye";
};

Sub.prototype = new Base();
var tst = new Sub();

for (var i in tst) {
    console.log(tst.hasOwnProperty(i) + i + tst[i]);
}

Object.keys(tst).forEach(function (val) {
    console.log(val + tst[val]);
});
Sam神乐番长2020/03/13 16:47:03

Douglas Crockford建议在JavaScript:The Good Parts(第24页)中避免使用该for in语句。

If you use for in to loop over property names in an object, the results are not ordered. Worse: You might get unexpected results; it includes members inherited from the prototype chain and the name of methods.

Everything but the properties can be filtered out with .hasOwnProperty. This code sample does what you probably wanted originally:

for (var name in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, name)) {
        // DO STUFF
    }
}
小小小胖2020/03/13 16:47:03

数组稀疏时,两者不相同。

var array = [0, 1, 2, , , 5];

for (var k in array) {
  // Not guaranteed by the language spec to iterate in order.
  alert(k);  // Outputs 0, 1, 2, 5.
  // Behavior when loop body adds to the array is unclear.
}

for (var i = 0; i < array.length; ++i) {
  // Iterates in order.
  // i is a number, not a string.
  alert(i);  // Outputs 0, 1, 2, 3, 4, 5
  // Behavior when loop body modifies array is clearer.
}
Tom小小蛋蛋2020/03/13 16:47:03

所有主要浏览器的2012当前版本的更新答案 -Chrome,Firefox,IE9,Safari和Opera支持ES5的本机array.forEach。

除非您有某些本机支持IE8的理由(请记住可以为这些用户提供ES5-shim或Chrome框架,这将提供适当的JS环境),否则使用该语言的适当语法会更干净:

myArray.forEach(function(item, index) {
    console.log(item, index);
});

有关array.forEach()的完整文档,请访问MDN。

Davaid梅2020/03/13 16:47:03

请注意,本机Array.forEach方法现已得到广泛支持

L神无Mandy2020/03/13 16:47:03

该选择应基于对哪种习语最了解。

使用以下方法迭代数组:

for (var i = 0; i < a.length; i++)
   //do stuff with a[i]

使用以下方法来迭代用作关联数组的对象:

for (var key in o)
  //do stuff with o[key]

除非您有惊天动地的理由,否则请遵循既定的使用模式。

GIZO-俊宏2020/03/13 16:47:03

根据使用哪种循环以及使用哪种浏览器,性能会有差异。

例如:

for (var i = myArray.length-1; i >= 0; i--)

在某些浏览器中的速度几乎是:

for (var i = 0; i < myArray.length; i++)

但是,除非您的数组很大,否则您必须不断地循环它们,否则它们的速度都足够快。我严重怀疑数组循环是否会成为您项目中的瓶颈(或任何其他与此项目有关的项目)