如何更有效地做到这一点?

时间:2010-06-04 05:29:51

标签: javascript arrays optimization loops

让我们假设我们应该得到一些数据......

var data = [];

//some code omitted that might fill in the data (though might not)

然后我们需要对数据做些什么。我的问题是如何更有效地做到这一点。 像这样?:

if (data.length) {
    for (var i = 0; i < data.length; i++) {
        //iterate over the data and do something to it
    }
}

还是这样?:

for (var i = 0; i < data.length; i++) {
    //iterate over the data and do something to it
}

关键是在迭代之前是否检查长度?

6 个答案:

答案 0 :(得分:8)

我认为不值得检查是否根据for的{​​{1}}执行length循环,因为如果{data可能会在性能方面没有太大差异{1}}循环只执行几次。

但一般来说,首先获得长度而不是将其设置为for会更快,因为每次都需要访问变量。至于哪种方式最有效地循环数据,不同的浏览器针对不同类型的循环进行了优化。但是,它只是认真慢的IE(在下面的测试中比其他浏览器慢几个数量级)所以我认为优化其他浏览器可能不值得。

以下是基准测试的结果(最快用+表示,最慢用 - 表示):

           FF      Chrome  Safari  Opera   IE6      IE7      IE8 
Method 1  +0.163+  0.221   0.246   0.269  -11.608- -12.214- -7.657-
Method 2   0.175  +0.133+  0.176  +0.147+   8.474    8.752   3.267
Method 3   0.206   0.235   0.276   0.245    8.002    8.539   3.651
Method 4   0.198   0.372   0.447   0.390   +6.562+  +7.020+  2.920
Method 5   0.206   0.372   0.445  -0.400-   6.626    7.096  +2.905+
Method 6   0.176   0.167  +0.175+  0.223    7.029    8.085   3.167
Method 7  -0.263- -0.567- -0.449-  0.413    6.925    7.431   3.242

方法1:使用“标准”i<data.length循环:

for

方法2 :使用“标准”for (var i=0; i<data.length; i++) { var x = data[i] } 循环,分配for,使其不必每次都可以访问:

length

方法3:这类似于jQuery在for (var i=0, len=data.length; i<len; i++) { var x = data[i] } 中使用的方法。请注意分配给$.each(),这样就不必每次都获得len

length

方法4:使用for (var x=data[0], len=data.length, i=0; i<len; x=data[++i]) {} 循环,前进。 警告:需要数组中的每个项目评估为while,即不是truefalse0nullundefined等等!

''

方法5:与方法4相同,仅使用var x, i=0 while (x = data[i++]) {} 执行相同操作:

for

方法6:使用for (var x,i=0; x=data[i++];) {} 向后循环:

while

方法7 :使用方法4 /方法5,但无需将项目评估为var i = data.length while (i--) { var x = data[i] } ,替换true

x = data[i++]

首先检查var x, i=0, len=data.length while ((x=data[i++]) || i<len) {} 是否评估为data[i++],然后检查它是否是最后一项,以便在IE中具有相似的性能,truenull等问题更少在数组中。请注意,在这种情况下使用false vs while时没有明显的差异,但我更喜欢for因为我认为它更清楚。

我通常不喜欢优化,除非有一个特定的长期运行任务,因为它往往以可读性为代价 - 请只有在你有一个特定的案例,你有大量的数据来执行它加载等: - )

编辑:由于方法4/5在IE上速度如此之快,因此添加了副作用较少的版本。

编辑2:重做所有测试,这次没有任何浏览器扩展且更长时间。这是为了完整起见的代码(抱歉这篇文章很长:)

while

答案 1 :(得分:4)

我认为第二个版本更具惯用性,不仅仅是在JavaScript中,而是在大多数编程语言中。如果您关心时序,可以将数组的长度保存在变量中,并在循环中使用该变量,但我不认为这是必要的:

var data = [];
var length = data.length;
for (var i = 0; i < length; i++) {
    //iterate over the data and do something to it
}

答案 2 :(得分:2)

检查data.length并迭代它需要什么?

只需使用for循环即可。

答案 3 :(得分:2)

我通常不会在迭代前检查长度。事实上,for循环本身将检查每次迭代的长度

没有值得一提的性能开销。在长度为0的情况下,唯一的额外指令是将在内存中声明新的int。你需要成千上万的人才能感受到毫秒的影响。

答案 4 :(得分:1)

如果数据没有项目,那么data.lenght将为0.因此,你的循环永远不会触发,因为i = 0已经小于数组中的项目数。因此,选项2很好。

但是,在执行托管代码时,您可能希望在对该对象调用.length之前检查NULL对象。

答案 5 :(得分:1)

我认为在这种情况下循环data的最有效方法是:

var pos = data.length;
while (pos--) {
  // do something to => data[pos]
}

,尽可能减少查找和声明。 它将向后迭代这些项目,但这可能并不总是令人担忧。