JavaScript属性会在每次调用时进行计算吗?

时间:2020-03-06 15:05:32  来源:igfitidea点击:

由于length是JavaScript属性,因此是否使用

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

或者

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

解决方案

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

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

如果myArray是javascript数组,那么不必担心,它只是在对象上查找属性,而变量用法也是如此。

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

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

但是对于数组,我不必理会。

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

使用push,pop,shift,unshift,concat,splice等时,它将更改。否则,它只是一个Number -每次调用其值时都是相同的实例。

但是,只要我们不显式覆盖它(array.length = 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

..在任何非边缘情况下都没有关系。

虽然不会在每次调用时都计算length属性,但是当我们缓存属性查找时,后一种版本会更快。即使使用最新的JS实现(V8,TraceMonkey,SquirrelFish Extreme)使用高级(例如SmallTalk时代;))属性缓存,属性查找仍然比第二个版本至少多一个条件分支。

Array.length不是常数,但是因为JS Array是可变的,所以`push,pop,array [array.length] = 0等都可能改变它。

我们还可以从诸如document.getElementsBySelector之类的调用中获得DOM之类的NodeList之类的其他概念,在这种情况下,可以在迭代时重新计算长度。但是,如果确实重新计算了长度,则很有可能实际上也已更改了该长度,因此手动缓存输出可能无效。

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

如果要实现它,我将按照Jonathan指出的那样进行,但是要使用Array对象的" length"属性。

如果我们有想法在循环期间可能会更改,那么当然应该检查每个循环...

-否则,多次询问一个对象显然很麻烦,就像将其放置在if语句的评估属性中一样...

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

-仅在特殊情况下,我们应该考虑其他方法!-)

我认为,对我们问题的意图的答案是,是的,如果我们在循环中修改数组,则每次循环迭代都会重新计算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