你认为for in和for循环有很大的不同吗?您更喜欢使用什么样的“for”以及为什么?
假设我们有一组关联数组:
var myArray = [{'key': 'value'}, {'key': 'value1'}];
所以我们可以迭代:
for (var i = 0; i < myArray.length; i++)
和
for (var i in myArray)
我没有看到很大的不同。有任何性能问题吗?
答案 0 :(得分:543)
选择应基于最能理解的习语。
使用以下代码迭代数组:
for (var i = 0; i < a.length; i++)
//do stuff with a[i]
使用以下函数迭代用作关联数组的对象:
for (var key in o)
//do stuff with o[key]
除非你有惊天动地的原因,否则请坚持既定的使用方式。
答案 1 :(得分:160)
Douglas Crockford建议JavaScript: The Good Parts(第24页)避免使用for in
语句。
如果使用for in
循环对象中的属性名称,则不会对结果进行排序。更糟糕:你可能会得到意想不到的结果;它包括从原型链继承的成员和方法的名称。
可以使用.hasOwnProperty
过滤除属性之外的所有内容。此代码示例执行您最初可能需要的内容:
for (var name in obj) {
if (Object.prototype.hasOwnProperty.call(obj, name)) {
// DO STUFF
}
}
答案 2 :(得分:62)
jQuery的each(callback)
方法默认使用for( ; ; )
循环,如果长度为for( in )
,则仅使用undefined
。
因此,我认为使用此功能时可以安全地假设正确的顺序。
示例强>:
$(['a','b','c']).each(function() {
alert(this);
});
//Outputs "a" then "b" then "c"
使用它的缺点是,如果你正在做一些非UI逻辑,你的功能将不太容易移植到其他框架。 each()
函数最好保留用于jQuery选择器,否则for( ; ; )
可能是可取的。
答案 3 :(得分:29)
根据您使用的循环类型以及浏览器的不同,存在性能差异。
例如:
for (var i = myArray.length-1; i >= 0; i--)
在某些浏览器上的速度几乎是以下的两倍:
for (var i = 0; i < myArray.length; i++)
然而,除非你的阵列是巨大的,否则你不断循环它们都足够快。我严重怀疑阵列循环是你项目(或任何其他项目)的瓶颈
答案 4 :(得分:26)
请注意,原生Array.forEach方法现在是widely supported。
答案 5 :(得分:24)
更新了2012年的答案所有主流浏览器的当前版本 - Chrome,Firefox,IE9,Safari和Opera支持ES5的原生array.forEach。
除非你有理由本机支持IE8(记住ES5-shim或Chrome框架可以提供给这些用户,这将提供一个合适的JS环境),简单地使用该语言的正确语法更简洁:
myArray.forEach(function(item, index) {
console.log(item, index);
});
答案 6 :(得分:14)
使用forEach跳过原型链
只是@nailer's answer above的快速附录,使用带有Object.keys的forEach意味着您可以避免迭代原型链而无需使用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]);
});
答案 7 :(得分:14)
我认为您应该根据需要选择迭代方法。我建议你实际上不要永远循环使用Array
结构的原生for in
。正如Chase Seibert刚才指出的那样,和的速度要慢一些,与原型框架不兼容。
有一个很棒的benchmark on different looping styles that you absolutely should take a look at if you work with JavaScript。不要做早期优化,但是你应该把这些东西留在脑后。
我会使用for in
来获取对象的所有属性,这在调试脚本时特别有用。例如,当我探索不熟悉的对象时,我喜欢使用这条线:
l = ''; for (m in obj) { l += m + ' => ' + obj[m] + '\n' } console.log(l);
它将整个对象的内容(与方法体一起)转储到我的Firebug日志中。 非常方便。
答案 8 :(得分:13)
当数组稀疏时,两者不一样。
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.
}
答案 9 :(得分:7)
这是我做过的事。
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';
}
});
我刚刚做了这个,所以我愿意接受建议:)
答案 10 :(得分:6)
我会根据我想引用这些项目的方式使用不同的方法。
如果您只想要当前项目,请使用foreach。
如果您需要索引器进行相对比较,请使用此选项。 (即,这与上一个/下一个项目相比如何?)
我从未注意到性能差异。我一直等到遇到性能问题才担心它。
答案 11 :(得分:4)
使用 for(var i in myArray),你也可以遍历对象, i 将包含密钥名称,你可以通过 myArray访问该属性[ I] 。另外,您将添加到对象中的任何方法也将包含在循环中,即,如果您使用任何外部框架(如jQuery或原型),或者如果您直接向对象原型添加方法,则 i 将指向这些方法。
答案 12 :(得分:4)
小心!
如果您有多个脚本标记并且您正在搜索标记属性中的信息,则必须使用带有for循环的.length属性,因为它不是简单数组而是HTMLCollection对象。
https://developer.mozilla.org/en/DOM/HTMLCollection
如果你使用foreach语句(你的列表中的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
答案 13 :(得分:3)
如果您真的想加快代码速度,那该怎么办?
for( var i=0,j=null; j=array[i++]; foo(j) );
它有点在for语句中使用while逻辑,并且它不那么冗余。另外firefox有Array.forEach和Array.filter
答案 14 :(得分:3)
我看到使用对象,原型和数组的“for each”存在问题
我的理解是for each用于对象和NOT数组的属性
答案 15 :(得分:3)
对于Arrays上的in循环与Prototype不兼容。如果您认为将来可能需要使用该库,那么坚持使用for循环是有意义的。
答案 16 :(得分:3)
根据jsperf的更短和最好的代码是
keys = Object.keys(obj);
for (var i = keys.length; i--;){
value = obj[keys[i]];// or other action
}
答案 17 :(得分:1)
使用Array()。forEach循环来利用并行性
答案 18 :(得分:1)
for(;;)适用于数组:[20,55,33]
for..in 适用于对象:{x:20,y:55:z:33}
答案 19 :(得分:0)
小心!!! 我在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
答案 20 :(得分:0)
两者之间存在重要差异。 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(;;)语句。
答案 21 :(得分:0)
虽然两者非常相似,但存在细微差别:
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
}
在这种情况下输出为:
循环标准:
ARRAY [0] = A
ARRAY [1] = B
ARRAY [2] = C
console.log("For-in loop:");
for (var key in array)
{
console.log(" array[" + key + "] = " + array[key]); //For-in loop output
}
虽然在这种情况下输出是:
FOR-IN LOOP:
ARRAY [1] = B
ARRAY [2] = C
ARRAY [10] = D
ARRAY [ABC] = 123
答案 22 :(得分:0)
for in语句允许循环遍历对象的所有属性的名称。不幸的是,它还遍历通过原型链继承的所有成员。当兴趣在数据成员中时,这具有提供方法功能的不良副作用。