JavaScript for … in和for … for

你认为在…和循环中有很大的不同吗? 你喜欢用什么样的“for”,为什么?

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

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

所以我们可以迭代:

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

和:

 for (var i in myArray) 

我没有看到很大的区别。 有没有任何性能问题?

选择应该基于哪一个习语是最好理解的。

一个数组是迭代使用:

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

被用作关联数组的对象使用下面的代码迭代:

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

除非你有地球震动的原因,否则坚持已有的使用模式。

道格拉斯·克罗克福德(Douglas Crockford)在JavaScript中推荐:Good Part (第24页)以避免使用for in语句。

如果您使用for in来循环对象中的属性名称,则结果不会被排序。 更糟的是:你可能会得到意想不到的结果 它包括从原型链继承的成员和方法的名称。

除了属性以外的所有东西都可以用.hasOwnProperty过滤掉。 这个代码示例做你最初可能想要的:

 for (var name in obj) { if (Object.prototype.hasOwnProperty.call(obj, name)) { // DO STUFF } } 

仅供参考 – jQuery用户


jQuery的each(callback)方法默认使用for( ; ; )循环, 只有当长度undefined才会使用for( in )

因此,我认为在使用这个功能时,假定正确的顺序是安全的。

例如

 $(['a','b','c']).each(function() { alert(this); }); //Outputs "a" then "b" then "c" 

使用它的缺点是,如果你正在做一些非UI逻辑,你的函数将不能移植到其他框架。 each()函数可能最适合用于jQuery选择器, for( ; ; )可能是最好的。


有什么性能差异取决于你使用什么样的循环和浏览器。

例如:

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

在某些浏览器上的速度几乎是以下速度的两倍:

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

但是,除非你的数组是巨大的,或者你经常循环它们都足够快。 我严重怀疑数组循环是您的项目(或任何其他项目)的瓶颈,

请注意,本机Array.forEach方法现在被广泛支持 。

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。

使用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]); }); 

我第二个意见是你应该根据你的需要选择迭代方法。 我建议你实际上不要通过本地Array来循环结构。 正如Chase Seibert刚才所指出的那样,它的速度比较慢,与原型框架不兼容。

对于不同的循环风格有一个很好的基准,如果你使用JavaScript,你绝对应该看看 。 不要做早期的优化,但是你应该把这些东西放在脑后。

我将使用for in来获取对象的所有属性,这在调试脚本时特别有用。 例如,当我探索不熟悉的对象时,我喜欢这条线:

 l = ''; for (m in obj) { l += m + ' => ' + obj[m] + '\n' } console.log(l); 

它将整个对象的内容(与方法体一起)转储到我的Firebug日志中。 非常方便。

当数组稀疏时,两者不一样。

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

这是我做的。

 function foreach(o, f) { for(var i = 0; i < o.length; i++) { // simple for loop f(o[i], i); // execute a function and make the obj, objIndex available } } 

这是你将如何使用它
这将工作在数组和对象(如HTML元素列表)

 foreach(o, function(obj, i) { // for each obj in o alert(obj); // obj alert(i); // obj index /* say if you were dealing with an html element may be you have a collection of divs */ if(typeof obj == 'object') { obj.style.marginLeft = '20px'; } }); 

我只是这样做,所以我打开建议:)

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

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

如果您需要索引器进行相对比较,请使用此选项。 (即这与前一个/下一个项目相比如何?)

我从来没有注意到性能差异。 我会等到性能问题再担心它。

for(var i myArray),你也可以遍历对象, 将包含关键字的名字,你可以通过myArray [i]访问属性。 另外,任何你添加到对象中的方法都会被包含在循环中,也就是说,如果你使用任何外部框架,如jQuery或prototype,或者直接添加方法到对象原型,那么会指向那些方法。

小心!

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

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

如果你在foreach语句中使用(var i在你的List中),它会在大多数浏览器中返回HTMLCollection的proterties和方法!

 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

数组中的in循环与Prototype不兼容。 如果您认为将来可能需要使用该库,那么坚持循环是有意义的。

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

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

我的理解是,每个对象的属性和NOT数组

如果你真的想加快你的代码,那又怎样?

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

在for语句中有一个while逻辑,它不那么多余。 另外firefox有Array.forEach和Array.filter

根据jsperf的更短和最好的代码是

 keys = Object.keys(obj); for (var i = keys.length; i--;){ value = obj[keys[i]];// or other action } 

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

小心!!! 我在Mac OS中使用Chrome 22.0,而且每个语法都有问题。

我不知道这是一个浏览器问题,JavaScript的问题或代码中的一些错误,但它是非常奇怪的。 对象之外,它完美的作品。

 var MyTest = { a:string = "a", b:string = "b" }; myfunction = function(dicts) { for (var dict in dicts) { alert(dict); alert(typeof dict); // print 'string' (incorrect) } for (var i = 0; i < dicts.length; i++) { alert(dicts[i]); alert(typeof dicts[i]); // print 'object' (correct, it must be {abc: "xyz"}) } }; MyObj = function() { this.aaa = function() { myfunction([MyTest]); }; }; new MyObj().aaa(); // This does not work myfunction([MyTest]); // This works 

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

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

两者之间有一个重要的区别。 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 

你可以使用if(myArray.hasOwnProperty(i)) 。 不过,在迭代数组时,我总是喜欢避免这种情况,只需使用for(;;)语句。