2

When I do something like this:

var o = new Array();
o[20] = true;
o[1000] = true;
o[4000] = true;

Is it reasonable to expect that only 3 elements will be allocated or can the implementation decide to suddenly allocate something with 4000 elements?
The reason I'm asking is that when I do this I see in firebug an indication that there are actually 4000 undefined in o. are they really there?

shoosh
  • 76,898
  • 55
  • 205
  • 325

5 Answers5

4

a) That code is not valid. You need either var o = {}; // object or var o = []; // array.

b) In the first case, the object is sparse. In the second, it may depend on the interpreter; in modern browsers it is also sparse. Try o[99999999] = "hi"; and see how much memory your browser does or does not allocate. If it does not go up by at least 10MB, your arrays are sparse.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • I'm fairly sure I remember Firefox fixing their implementation so that "o[2147483647]" doesn't suddenly use up all machine's memory. – Matthew Wilson Jan 26 '11 at 14:21
  • 2
    I don't think it depends on the interpreter. All the JavaScript runtimes will do is make sure that the "length" property remains correct (that is, one larger than the largest non-empty integer-indexed property). The only thing to worry about is the `new Array(n)` constructor when "n" is a large integer, because that function *does* pre-allocate. – Pointy Jan 26 '11 at 14:26
  • @Pointy I'll change my answer to say "may" depend; I am not personally aware of the implementation of all interpreters. It's possible (if pedantic) to imagine a non-popular or old interpreter with non-sparse behavior. – Phrogz Jan 26 '11 at 14:28
  • @Phrogz fair enough, but "in the wild" I think it's unlikely to be encountered. – Pointy Jan 26 '11 at 14:29
  • @Pointy, [the Array constructor](http://es5.github.com/#x15.4.2.2) *does not pre-allocate*, it just assigns the `length` property if the `n` argument is within the range of unsigned 32-bit integers... – Christian C. Salvadó Jan 26 '11 at 14:42
  • Really, @CMS? I've suffered out-of-memory errors on Firefox through buggy code that called `new Array(bigNumber)` accidentally. That was several years ago, however. (And indeed I just tried it in a Firefox instance, and it's still OK :-) – Pointy Jan 26 '11 at 14:44
4

Now that we know that o is an Array, I can answer you precisely.

No, the elements will not be 'allocated' or 'created'.

When you make an assignment of an index property to an Array object, which is greater than the actual length of the array two things happen:

  1. The index named property is created
  2. The length property is incremented, to be the index + 1

For example:

var o = [];
o[4000] = true;

o.hasOwnProperty(0); // false, the property doesn't exist
o.hasOwnProperty(1); // false
o.hasOwnProperty(4000); // true, the property exist

As you can see, the hasOwnProperty method returns false when we test the presence of the 0 or 1 properties, because they don't exist physically on the object, whereas it returns true for 4000, the property that was created.

When Firebug detects that the object being printed in the console is an array-like object, it will simply make a loop, showing each of the index values from 0 to length - 1.

Firebug detects array-like objects simply by looking if they have a length property whose its value is an unsigned 32-bit integer (less than 2^32 - 1), and if they have a splice property that is a function, for example, the following object will be detected and printed as an Array on the Firebug's console:

console.log({length:3, splice:function(){}});
// Firebug will log: `[undefined, undefined, undefined]`
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
1

I think this one answers the question.

Are Javascript arrays sparse?

And according to that one, arrays are spares, thats is, if you use for(item in array) you only get 3 items, not 4000 but if you use array.length it will take the larges integer value and return one larger, look here:

http://www.crockford.com/javascript/survey.html

Linkpad will use a for(item = 0; item < array.length; item++) and that one will return undefined for any index that is not present in the array.

Community
  • 1
  • 1
David Mårtensson
  • 7,550
  • 4
  • 31
  • 47
0

/* On the other hand, if you have a very large index any array manipulation will have to loop through each index- it won't skip from one defined item to the the next defined item.

*/

var A= [];
A[0]= 'a';
A[10]= 'b';
A[4000000]= 'c';
alert(A.filter(function(itm){
    return itm!= undefined;
}));
kennebec
  • 102,654
  • 32
  • 106
  • 127
-1

Javascript will generate all elements inbetween, always. You may want to use o.length to verify the length of the array. It will return 4000 and not 3.

Spliffster
  • 6,959
  • 2
  • 24
  • 19
  • This seems to contradict the other answers. – shoosh Jan 26 '11 at 14:21
  • This is not correct. Yes, "length" is adjusted, but that does not mean that other elements are "filled in" or "generated". All the interpreter does is set the "length" property to the correct value. – Pointy Jan 26 '11 at 14:25