29

我偶然发现了几种在 JavaScript 中循环的方法,我最喜欢的是:

for(var i = 0; i < a.length; i++){
    var element = a[i];
}

但是正如这里测试的那样(http://www.robertnyman.com/2008/04/11/javascript-loop-performance/),它可能应该被写成长度只计算一次。

在 jQuery 中有一个 .each 可以粘贴一个函数。我更喜欢这个,因为我不必像上面的解决方案那样输入两次数组。

如果 JavaScript 支持宏,那么你自己动手做就是小菜一碟,但遗憾的是它不支持。

那你们用什么?

4

9 回答 9

37

我已经开始在相关的地方使用迭代器。性能是合理的,但更重要的是它允许您封装循环逻辑:

function createIterator(x) {
    var i = 0;

     return function(){
       return x[i++];
    };
}

然后使用:

var iterator=createIterator(['a','b','c','d','e','f','g']);

iterator();

返回“一”;

iterator();

返回“b”;

等等。

要迭代整个列表并显示每个项目:

无功电流;

而(当前=迭代器())
{
    控制台.log(当前);
}

请注意,上述内容仅适用于迭代包含“非虚假”值的列表。如果此数组包含以下任何一项:

  • 0
  • 错误的
  • “”
  • 空值

上一个循环将在该项目处停止,并不总是您想要/期望的。

为了避免这种使用:

var current;

while((current=iterator())!==undefined)
{
   console.log(current);
}
于 2008-10-11T01:35:12.737 回答
10

对原始的小改进,只计算一次数组大小:

for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }

另外,我看到很多 for..in 循环。但请记住,它在技术上并不符合犹太教规,并且会特别导致 Prototype 出现问题:

for (i in a) { var element = a[i]; }
于 2008-10-11T01:51:57.697 回答
6

只需先将长度存储在变量中。

  var len = a.length;
  for (var i = 0; i < len; i++) {
    var element = a[i];
  }
于 2008-10-11T02:01:09.440 回答
6

我知道我迟到了,但我对不依赖于顺序的循环使用反向循环。

与@Mr. 非常相似。麝鼠 - 但简化了测试:

var i = a.length, element = null;
while (i--) {
  element = a[i];
}
于 2008-10-14T15:10:54.930 回答
2

您可以始终使用 while 循环,并事先计算数组限制。

Var max = a.length-1;
var i = 0;

while(i <= max)
{
var element = a[i];
i++;
}
于 2008-10-11T01:26:00.120 回答
1

如果数组中有很多元素并且速度是一个问题,那么您希望使用从最高到最低迭代的 while 循环。

  var i = a.length;
  while( --i >= 0 ) {
    var element = a[i];
    // do stuff with element
  }  
于 2008-10-11T18:49:45.410 回答
1

我自己不使用它,但我的一位同事使用这种风格:

var myArray = [1,2,3,4];
for (var i = 0, item; item = myArray[i]; ++i) {
    alert(item);
}

就像 Ash 的回答一样,如果您的数组中有“错误”值,这会遇到问题。为避免该问题,请将其更改为(item = myArray[i]) != undefined

于 2008-10-12T10:14:12.080 回答
0

我看不出使用标准 for(;;) 循环有什么问题。一个小测试

var x;
var a = [];
// filling array
var t0 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
    a[i] = Math.floor( Math.random()*100000 );
}

// normal loop
var t1 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
    x = a[i];
}

// using length
var t2 = new Date().getTime();
for( var i = 0; i < a.length; i++ ) {
    x = a[i];
}

// storing length (pollution - we now have a global l as well as an i )
var t3 = new Date().getTime();
for( var i = 0, l = a.length; i < l; i++ ) {
    x = a[i];
}

// for in
var t4 = new Date().getTime();
for( var i in a ) {
    x = a[i];
}

// checked for in
var t5 = new Date().getTime();
for( var i in a ) {
    if (a.hasOwnProperty(i)) {
        x = a[i];
    }
}

var t6 = new Date().getTime();
var msg = 'filling array: '+(t1-t0)+'ms\n'+
          'normal loop: '+(t2-t1)+'ms\n'+
          'using length: '+(t3-t2)+'ms\n'+
          'storing length: '+(t4-t3)+'ms\n'+
          'for in: '+(t5-t4)+'ms\n'+
          'checked for in: '+(t6-t5)+'ms';
console.log( msg );

结果是:

filling array: 227ms
normal loop: 21ms
using length: 26ms
storing length: 24ms 
for in: 154ms
checked for in: 176ms

所以:- 因为 in 是最长的,使用 length 属性(这是一个属性,不需要计算)几乎和首先存储它一样快 - 这只是比使用整数慢一点。
AND a for() 是循环数组的常用方法,这是每个人都期望和理解的。

All of them add a variable to the scope they run in - i - which is a common name for this use and so shouldn't be used for other things. Storing the length first adds another var - l - to the scope, which is unnecesary

于 2009-01-07T23:09:36.297 回答
-2

所以,首先你确定完美的 javascript 循环,我相信它应该是这样的:

ary.each(function() {$arguments[0]).remove();})

这可能需要prototype.js 库。

接下来,您对 arguments[0] 部分感到厌恶,并让代码从您的服务器框架自动生成。这仅在梯子位于海边时才有效。

现在,您已通过以下方式生成上述内容:

ary do: [:each | 每个元素删除]。

这带有完整的语法完成,并完全转换为上述 javascript。当他们阅读您的代码时,它会让以前没有使用 seasides 原型集成的人头晕目眩。它肯定也会让你感觉很酷。更不用说你可以在这里获得的极客增益。女孩们喜欢它!

于 2009-01-07T20:25:06.003 回答