9

由于长度是一个JavaScript属性,我是否使用它是否重要

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

或者

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

­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

4

8 回答 8

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

有关各种 Javascript 循环结构的基准,请参阅http://blogs.oracle.com/greimer/resource/loop-test.html 。

于 2008-10-03T19:24:22.703 回答
2

如果 myArray 是 javascript 数组,那么您不必担心它,它只是一个在对象上查找的属性,但变量使用也是如此。

如果 OTH 长度是由浏览器 DOM(尤其是 IE)提供的集合对象公开的属性,那么它可能会非常昂贵。因此,在枚举这样一个 DOM 提供的集合时,我倾向于使用:-

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

但对于数组我不打扰。

于 2008-10-03T19:26:01.453 回答
2

我认为你的问题意图的答案是,是的,如果你修改循环中的数组,array.length 属性会在每次迭代中重新计算。例如,下面的代码:

var arr = [1,2,3];
for(var i = 0; i < arr.length; i++){
  console.debug("i = " + i);
  console.debug("indexed value = " + arr[i])
  arr.pop();
}

将输出:

i = 0
indexed value = 1
i = 1
indexed value = 2

而这段代码:

var arr = [1,2,3];
var l = arr.length;
for(var i = 0; i < l; i++){
  console.debug("i = " + i);
  console.debug("indexed value = " + arr[i])
  arr.pop();
}

将输出:

i = 0
indexed value = 1
i = 1
indexed value = 2
i = 2
indexed value = undefined

-J

于 2008-10-05T20:54:35.893 回答
1

不,它不会在通话时重新计算。它在 Array 类中根据需要重新计算。

当您使用pushpopshiftunshiftconcatsplice等时,它会发生变化。否则,它只是一个 Number ——每次调用它的值时都是同一个实例。

但是,只要您不显式覆盖它(array.length = 0),每次调用都会准确。

于 2008-10-03T19:30:06.937 回答
1

不会在每次调用时计算长度属性,但后一个版本会更快,因为您正在缓存属性查找。即使是最新的 JS 实现(V8、TraceMonkey、SquirrelFish Extreme),它们使用高级(例如 SmallTalk 时代;))属性缓存,属性查找仍然比您的第二个版本多出至少一个额外的条件分支。

Array.length 不是恒定的,但是因为 JS 数组是可变的,所以push, pop, array[array.length]=0, etc可能都会改变它。

还有其他一些概念,例如NodeList您从调用中获得的 DOM document.getElementsBySelector,它们预计将是实时的,在这种情况下,长度可能会在您迭代时重新计算。但是,如果确实重新计算了长度,那么它很有可能实际上也会发生变化,因此手动缓存输出可能无效。

于 2008-10-03T22:05:15.110 回答
0

虽然第二种形式可能更快:

function p(f) { var d1=new Date(); for(var i=0;i<20;i++) f(); print(new Date()-d1) }
p(function(){for(var i=0;i<1000000; i++) ;})
p(function(){var a = new Array(1000000); for(var i=0;i<a.length; i++) ;})
> 823
> 1283

..在任何非边缘情况下都应该无关紧要。

于 2008-10-03T19:32:00.693 回答
0

根据ECMAScript 规范,它只是说明应该如何计算“长度”属性,但没有说明何时。我认为这可能取决于实现。

如果我要实现它,我会按照乔纳森指出的那样做,但如果是 Array 对象的“长度”属性。

于 2008-10-03T22:27:12.430 回答
0

如果您曾经想过它可能会在循环期间发生变化,那么当然应该检查每个循环...

-- 否则多次询问一个对象显然是疯了,如果你把它放在 if 语句的评估属性中......

if(i=0, iMax=object.length; iMax>i; i++)

-- 只有在特殊情况下你才应该考虑不这样做!-)

于 2008-10-05T20:35:07.040 回答