2

In JS are the lengths of an array cached or does it depend on the different engines/browsers?

Normally I'd assume that browsers' JS engines are pretty dumb and cache the length of arrays, for example:

var a   = [ ];
var l   = l;

function arrayPush(i)
{
    l   = a.push( i );
}

function arrayPop()
{
    var r   = a.pop();

    l   = a.length;

    return r;
}

(as a brief example, of course it'll be silly to replicate every array function but if it speeds stuff up it then it's worth it)

Ahmed Nuaman
  • 12,662
  • 15
  • 55
  • 87
  • @Oded - Pretty sure he's talking about computing the length vs having a length counter. – Polynomial Nov 17 '11 at 12:20
  • Can you elaborate a bit more? What do you mean by cached? Are you asking if it is recalculated or not every time f.e if you are getting it in a loop? – Umer Hayat Nov 17 '11 at 12:22
  • Perhaps Ahmed is worried that each access to `.length` will trigger a run-time count of elements within the array? (answer would be no). – Shawn Chin Nov 17 '11 at 12:22
  • Exactly what Shawn said. Should we cache lengths or are the engines that clever that they do it themselves? – Ahmed Nuaman Nov 17 '11 at 12:28
  • 1
    Looks like a dupe of: http://stackoverflow.com/questions/5752906/is-reading-the-length-property-of-an-array-really-that-expensive-an-operation which already has all the jsperf tests you could want. Short answer: yes in modern browsers, no in IE<9, 'maybe, but not very well' in IE9. – Gijs Nov 17 '11 at 12:37

3 Answers3

2

The array length is cached. It is updated each time the array is manipulated.


When you invoke the .push() method on the array, the array length is updated in step 6 of the algorithm:

Call the [[Put]] internal method of O with arguments "length", n, and true.

Source: http://es5.github.com/x15.4.html#x15.4.4.7


When you invoke the .pop() method of an array, the array length is updated in step 5.d of the algorithm:

Call the [[Put]] internal method of O with arguments "length", indx, and true.

Source: http://es5.github.com/x15.4.html#x15.4.4.6


When you assign a value to the array at an given index, the [[DefineOwnProperty]] internal method is invoked. The array length is updated in step 4.e.ii of the algorithm:

Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", oldLenDesc, and false as arguments. This call will always return true.

Source: http://es5.github.com/x15.4.html#x15.4.5.1

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • And is this for every browser engine? – Ahmed Nuaman Nov 17 '11 at 13:45
  • @AhmedNuaman I (obviously) don't know how certain browsers work internally, but I assume that all of them implement the internal algorithms mentioned in my answer. I can't think of a reason why any browser would not do that. – Šime Vidas Nov 17 '11 at 13:57
  • Hahaha, there are many crazy things that we, as rational developers, wonder why browsers do them, especially certain company's one ;) – Ahmed Nuaman Nov 17 '11 at 15:13
1

As elaborated on in this answer, modern browsers will have JS engines that will handle Array.length quite sensibly.

If you're worried about its performance on lesser JS engines, you can cache it if it's going to be used repeatedly e.g. when used in the stopping condition of a loop.

for (var i = 0, arrLength = arr.length; i < arrLength; i++) { }

It's unlikely that it will be SO slow that you need to maintain your own value for length (as in your example). That's unlikely to give you any noticeable performance gains, but will make your code less maintainable and more vulnerable to bugs.

Community
  • 1
  • 1
Shawn Chin
  • 84,080
  • 19
  • 162
  • 191
0

It depends on the implementation, though a sane browser should simply maintain a counter. If it's a very poor implementation, it'll probably have to traverse a data structure or something to get the size.

Normally you'd do something like this:

add(obj)
{
    buffer[ptr++] = obj;
}

getLength()
{
    return ptr;
}

When the buffer is empty, ptr is 0. Adding an object inserts it into buffer[0] and increments ptr by one, which will return 1 for the length, too. This means there's no need to do any form of "count" operation when you want the length.

Polynomial
  • 27,674
  • 12
  • 80
  • 107
  • 1
    Arrays stored as linked lists? really? – Shawn Chin Nov 17 '11 at 12:25
  • @ShawnChin - No, because that'd be silly. Hence why I said "if it's a very poor implementation". – Polynomial Nov 17 '11 at 12:25
  • 1
    Just thought that can be misleading especially to the unacquainted. i.e. the "poor implementation" may well be referring to the repeated traversal (rather than the choice of data structure). – Shawn Chin Nov 17 '11 at 12:31
  • Again this doesn't take into account array's functions such as `pop()`, `shift()`, etc... – Ahmed Nuaman Nov 17 '11 at 12:32
  • @AhmedNuaman - Sure it does. When you `pop()` or `shift()` the `ptr` value will still point to the end of the buffer. Since they change the size of the buffer, the `ptr` value still represents size. – Polynomial Nov 17 '11 at 12:33