views:

330

answers:

4

That is, if I use the current time as an index into the array:

array[Date.getTime()] = value;

will the interpreter instantiate all the elements from 0 to now? Do different browsers do it differently?

I remember there used to be a bug in the AIX kernel, which would create pseudo-ttys on request, but if you did, say, "echo > /dev/pty10000000000" it would create /dev/pty0, /dev/pty1, .... and then fall over dead. It was fun at trade shows, but I don't want this to happen to my customers.

+5  A: 

Yes, they are. They are actually hash tables internally, so you can use not only large integers but also strings, floats, or other objects. All keys get converted to strings via toString() before being added to the hash. You can confirm this with some test code:

<script>
  var array = [];
  array[0] = "zero";
  array[new Date().getTime()] = "now";
  array[3.14] = "pi";

  for (var i in array) {
      alert("array["+i+"] = " + array[i] + ", typeof("+i+") == " + typeof(i));
  }
</script>

Displays:

array[0] = zero, typeof(0) == string
array[1254503972355] = now, typeof(1254503972355) == string
array[3.14] = pi, typeof(3.14) == string

Notice how I used for...in syntax, which only gives you the indices that are actually defined. If you use the more common for (var i = 0; i < array.length; ++i) style of iteration then you will obviously have problems with non-standard array indices.

John Kugelman
Are arrays just a regular JS object with that stores index/values in the normal "properties" mechanism? That's what your code seems to suggest. I would guess then that an JS array just has some additional prototype methods then, as icing on the object cake?
Matt
most JS implementations store numerically indexed properties in an actual array if possible; that's behind-the-scenes magic, though: from a language standpoint, arrays are regular objects with a magic `length` property
Christoph
There is also magic in the `for...in` syntax which hides things like `length` so you only iterate over the array indices and not an array's properties or methods. One common problem people have is adding things to `Object.prototype` or `Array.prototype` which then breaks all `for...in` loops as these added properties/methods are not hidden.
John Kugelman
@John: `length` is only invisible in `for..in` loops because it has the `DontEnum` flag set; in ES5, the property attribute is called `enumerable` and can be explicitly set via `Object.defineProperty()`
Christoph
Your example simply proves that JavaScript arrays **are not** sparse.
Randell
All object keys in JavaScript are always `String`; anything else you put in the subscript gets `toString()`-ed. Combine this with the integer imprecision of large Number and it means if you set `a[9999999999999999]=1`, `a[10000000000000000]` will be 1 (and many more surprising behaviours). Using non-integers as keys is very unwise, and arbitrary objects are right out.
bobince
Then shalt thou only use Strings as object keys, no more, no less. String shall be the type thou shalt use, and the type of the key shall be String. Integer shalt thou not use, neither use thou non-integers, excepting that thou then proceed to cast to String. Arbitrary objects are right out.
Crescent Fresh
Array indexes must be integers. array[3.14] = pi works because Array inhereits from Object. Example: var x=[];x[.1] = 5; Then x has a length of 0 still.
Mike Blandford
Wow. var y = {}; var x = []; x[y] = 5; Then x["[object Object]"] is 5.
Mike Blandford
+6  A: 

How exactly JavaScript arrays are implemented differs from browser to browser, but they generally fall back to a sparse implementation - most likely the same one used for property access of regular objects - if using an actual array would be inefficient.

You'll have to ask someone with more knowledge about specific implementations to answer what excatly triggers the shift from dense to sparse, but your example should be perfectly safe. If you want to get a dense array, you should call the constructor with an explicit length argument and hope you'll actually get one.

See this answer for a more detailed description by olliej.

Christoph
THanks everyone! It's now working in Firefox. Onward with the project!
Berry
A: 

Javascript objects are sparse, and arrays are just specialized objects with an auto-maintained length property (which is actually one larger than the largest index, not the number of defined elements) and some additional methods. You are safe either way; use an array if you need it's extra features, and an object otherwise.

Justin Love
that's from a language standpoint; implementations actually use real arrays to store dense numeric properties
Christoph
A: 

You could avoid the issue by using a javascript syntax designed for this sort of thing. You can treat it as a dictionary, yet the "for ... in ... " syntax will let you grab them all.

var sparse = {}; // not []
sparse["whatever"] = "something";
John Fisher