JavaScript……In vs for

你认为……有很大的不同吗?In和for循环?你更喜欢用哪种for ?为什么?

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

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

所以我们可以迭代:

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

和:

for (var i in myArray)

我看不出有什么大的不同。是否存在性能问题?

293370 次浏览

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

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

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

如果需要索引器进行相对比较,请使用for。(也就是说,这与上一项/下一项相比如何?)

我从来没有注意到性能上的差异。我会等到出现性能问题时再担心。

选择应该基于哪个成语最容易理解。

使用以下方法迭代数组:

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

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

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

除非你有惊天动地的理由,否则就坚持既定的使用模式。

根据使用的循环类型和浏览器的不同,会有不同的性能。

例如:

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

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

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

然而,除非你的数组是巨大的,或者你不断地循环它们,所有的都足够快。我严重怀疑数组循环是你的项目(或任何其他项目)的瓶颈。

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

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

我认为你应该根据你的需要来选择迭代方法。我建议你实际上不要通过带有for in结构的本机Array进行循环。它更慢而且,正如Chase Seibert刚才指出的那样,与Prototype框架不兼容。

有一个优秀的如果你使用JavaScript,你绝对应该看看这些不同的循环风格。不要做早期的优化,但你应该把这些东西放在你脑后的某个地方。

我会使用for in来获取对象的所有属性,这在调试脚本时特别有用。例如,当我探索不熟悉的物体时,我喜欢把这句话放在手边:

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

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

Douglas Crockford在JavaScript:好的部分(第24页)中建议避免使用for in语句。

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

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

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

我曾见过使用对象、原型和数组的“for each”的问题

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

这是我做的事情。

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';
}
});

我只是做了这个,所以我愿意听取建议:)

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=0,j=null; j=array[i++]; foo(j) );

它有点像在for语句中有while逻辑而且它不那么冗余。firefox也有Array。forEach和Array.filter

注意本机Array。forEach方法现在是广泛的支持

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

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

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

使用forEach跳过原型链

只是@nail的答案在上面的一个快速补充,使用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()。forEach循环利用并行性

小心!

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

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

如果你使用foreach语句for(var i in yourList),它将在大多数浏览器中返回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应该返回一个节点列表,大多数浏览器都返回一个HTMLCollection: https://developer.mozilla.org/en/DOM/document.getElementsByTagName < / p >
< p >小心! ! 我在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

根据jsperf,更短且最好的代码是

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

(,)代表数组: [20,55,33]

对. .用于对象: {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-in。不过,在数组上迭代时,我总是倾向于避免这种情况,只使用for(;;)语句。

尽管它们非常相似,但有一个微小的区别:

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