views:

334

answers:

8

Since length is a Javascript property, does it matter whether I use

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

OR

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

Thank you.

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

See http://blogs.sun.com/greimer/resource/loop-test.html for benchmarks of various Javascript loop constructs.

Grant Wagner
The difference between the two approaches is negligable for an array. It only becomes significant when dealing with the DOM.
AnthonyWJones
+2  A: 

If myArray is javascript array then it doesn't matter enough for you to worry about it, its just a property look up on an object but then so is variable usage.

If OTH length is a property exposed by a collection object provided by a browsers DOM (especially IE) then it can be surprisingly expensive. Hence when enumerating such a DOM provided collection I tend to use:-

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

but for arrays I don't bother with that.

AnthonyWJones
accessing a local variable is not a property access -- it is a much faster direct lookup, with varying degrees of directness depending on implementation. No major implementation (excluding IE of course *sigh*) does an actual property lookup anymore.
olliej
+1  A: 

No. It doesn't recalculate on call. It recalculates as required within the Array class.

It'll change when you use push, pop, shift, unshift, concat, splice, etc. Otherwise, it's just a Number -- the same instance every time you call for its value.

But, as long as you don't override it explicitly (array.length = 0), it'll be accurate with each call.

Jonathan Lonowski
A: 

While the second form may be faster:

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

..it shouldn't really matter in any non-edge case.

Nickolay
+1  A: 

The length property is not computed on each call, but the latter version will be faster as you are caching the property lookup. Even with the most up to date JS implementations (V8, TraceMonkey, SquirrelFish Extreme) which use advanced (eg. SmallTalk era ;) ) property caching the property lookup is still at least one extra conditional branch more than your second version.

Array.length is not constant however as JS Arrays are mutable, so push, pop, array[array.length]=0, etc may all change it.

There are other concepts like the DOM NodeLists that you get from calls like document.getElementsBySelector which are expected to be live in which case the length may be recomputed as you iterate. But then if the length does get recomputed there's a good chance that it will also have actually changed, so manually caching the output may not be valid.

olliej
A: 

According to the ECMASCRIPT specification, it just tells how the "length" property should be calculated, but it doesn't says when. I think that it might be implementation dependant... If I we're to implement it, I would do as Jonathan pointed out, but that in case of the "length" property from the Array objects...

Pablo Cabrera
A: 

If you ever has an idea that it could change during the looping then of course it should be checked for every loop ...

-- else it's obviously nuts to ask an object several times, as it would be if you place it in the evaluation-property of the if-statement ...

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

-- only in special cases you should think of doing otherwise !-)

roenving
+1  A: 

I think the answer to the intent of your question is, yes, the array.length property gets recalculated each iteration through the loop if you modify the array in the loop. For example, the following code:

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

will output:

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

whereas this code:

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

will output:

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

-J

jvenema