当前位置:  开发笔记 > 编程语言 > 正文

JavaScript for ... in vs for

如何解决《JavaScriptforinvsfor》经验,为你挑选了11个好方法。

你认为for in和for循环有很大的不同吗?您更喜欢使用什么样的"for"?为什么?

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

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

所以我们可以迭代:

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

和:

for (var i in myArray)

我没有看到很大的不同.有任何性能问题吗?



1> AnthonyWJone..:

选择应该基于哪个成语最好理解.

使用以下代码迭代数组:

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

使用以下对象作为关联数组进行迭代:

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

除非你有惊天动地的原因,否则坚持既定的使用模式.


正如在另一个答案中所评论的那样,"for ... in"对于Arrays不能正常工作,因为它会遍历所有Array属性和方法.因此,您应该仅使用"for ... in"来迭代对象属性.否则,坚持"for(i = 0; i 应该提到的是,使用for ... in过滤if语句是一个很好的做法.Object"obj.hasOwnProperty(member)"有一个方便的方法,它检查迭代器返回的成员是否实际是该对象的成员.请参阅:http://javascript.crockford.com/code.html
@UpTheCreek:当数组实际上是由HTMLDOM返回时,这肯定是正确的,但是,我想知道在看到明显的差异之前,标准javascript数组需要多大?就个人而言,我会保持代码尽可能简单,直到证明有必要做一些不同的事情.
@Pichan我认为你的意思是你的for循环条件中的`i
2> Benno Richte..:

Douglas Crockford建议使用JavaScript:好的部分(第24页)以避免使用该for in语句.

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

除了属性之外的所有东西都可以过滤掉.hasOwnProperty.此代码示例执行您最初可能需要的内容:

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


for ... in非常适合循环对象属性.它不适合循环数组元素.如果你无法理解这些场景之间的区别,那么是的,你应该避免... in; 否则,坚持下去.
请不要忘记**声明**`name`变量:`for(var name in object)...`,否则,如果该代码在函数内,例如,`name`变量最终为全局对象的属性(对*未声明的标识符*的赋值),在新的ECMAScript 5 Strict Mode中,该代码将抛出一个`ReferenceError`.
想要强调它没有被订购的事实!这可能是一个大问题,并且很难捕获.
@Nosredna:有一个关于Chrome的迭代顺序的问题,由John Resig提出,标记为WontFix.http://code.google.com/p/chromium/issues/detail?id=883.即使在Chrome之前,如果您删除然后再次添加属性,则浏览器的顺序也不相同.IE 9的行为也很像chrome(据说可以提高速度).所以...请不要传播不准确的信息,你要非常天真地依赖它.
+1表示"它包括从原型链继承的成员和方法的名称." 例如,如果有人碰巧使用加载了Prototype的代码(即使你的代码实际上没有使用它),你会很开心.

3> Jason..:

仅供参考 - jQuery用户


jQuery的each(callback)方法for( ; ; )默认使用循环,并且for( in ) 在长度为时才使用undefined.

因此,我会说使用此功能时可以安全地假设正确的顺序.

示例:

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

使用它的缺点是,如果你正在做一些非UI逻辑,你的功能将不太容易移植到其他框架.该each()函数可能最好保留用于jQuery选择器,for( ; ; )否则可能是可取的.



总是有http://documentcloud.github.com/underscore/,它有_.each和许多其他有用的功能

4> Gene..:

根据您使用的循环类型和浏览器,存在性能差异.

例如:

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

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

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

但是,除非你的阵列是巨大的,否则你不断循环它们都足够快.我严重怀疑阵列循环是你项目的瓶颈(或者对于那个问题的任何其他项目)


我倾向于使用`for(var i = myArray.length; i - ;)`
在循环之前将"myArray.length"存储到变量中会使性能差异消失吗?我的猜测是"是".
不,'myArray.length'是一个属性,而不是对象上的方法 - 不进行计算以确定其值.将其值存储在变量中根本不会做任何事情.
就在这里.属性不是变量; 他们确实有获取/设置代码.
代码清晰易读.不是因为在当前时刻使用荒谬的大规模阵列,在某些浏览器中运行速度稍快一些.优化可能会改变,但代码的可读性(或缺乏代码)不会改变.编写其他人可以轻松遵循的代码,让优化者在适当的时候赶上.

5> Sam Dutton..:

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


它有什么作用?它是否有其他帖子中提到的问题(循环属性而不是数组元素)?此外,由于IE8不支持它,所以它被广泛支持有点紧张.
尽管*nix用户鄙视它,IE8绝大多数都是sub-windows7用户.这是浏览器市场的重要组成部分.
@Rauni - 我理解你的观点,但根据http://en.wikipedia.org/wiki/Usage_share_of_web_browsers#Summary_table,根据http://marketshare.hitslink,对于桌面设备,IE浏览器的份额不到40%. .com/browser-market-share.aspx?qprid = 2&qpcustomd = 0和其他网站,至少有8%的浏览器是IE 9.换句话说,大约70%的桌面浏览器支持Array.forEach,所以我不喜欢"认为'得到广泛支持'是不合理的.我没有检查,但移动支持(在WebKit和Opera浏览器上)可能更高.显然,地理上存在相当大的差异.

6> mikemaccana..:

更新了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.


@nailer这可以互换地用于数组和对象吗?

7> Damir Zekić..:

我的第二个意见是你应该根据你的需要选择迭代方法.我建议你其实并没有到遍历本地Arrayfor in结构.这是方法要慢,大通塞伯特指着刚才,不与原型框架相兼容.

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

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

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

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



8> Mike Samuel..:

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

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> meloncholy..:

使用forEach跳过原型链

只是上面@ nailer的答案的快速补遗,使用带有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]);
});


该死的,那是偷偷摸摸的.为了达到这个目的,值得阅读其他50篇文章.obj = {"粉红色":"鸭子",红色:"鹅"}; Object.keys(obj)=== ["粉红色","红色"]

10> 小智..:

这是我做的事情.

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

我刚刚做了这个,所以我愿意接受建议:)



11> Matt Lacey..:

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

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

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

我从未注意到性能差异.我会等到遇到性能问题然后再担心它.

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有