I disagree with Christoph when he states "array indices are converted to strings".
First, I think it is implementation dependent... I suppose (good) implementers will optimize array access, there are some smart ways to do it.
Actually, I did a little test, and although it is as good as most micro-benchmarks (ie. not super-reliable), it is interesting:
result = ""
var x;
var trueArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i; // To do the same operations
trueArray[i] = 1;
}
var endTime = new Date();
result += "With array: " + (endTime - startTime) + "\n";
var sArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sArray[x] = 1;
}
var endTime = new Date();
result += "With s array: " + (endTime - startTime) + "\n";
var objArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i;
objArray[x] = 1;
}
var endTime = new Date();
result += "With object(i): " + (endTime - startTime) + "\n";
var sobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sobjArray[x] = 1;
}
var endTime = new Date();
result += "With s object: " + (endTime - startTime) + "\n";
var iobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
iobjArray[i] = 1;
}
var endTime = new Date();
result += "With i object: " + (endTime - startTime) + "\n";
// Then display result
On IE6, I get: With array: 1453 With object: 3547
On FF 3.0, I get: With array: 83 With object: 226
On Safari 3.1, I get: With array: 140 With object: 313
On Opera 9.26, for some reason I don't get the result, but if I reduce to the tenth of number of loops, I get: With array: 47 With object: 516
Actually, I let Opera run while I type this, and finally got the result: With array: 281 With object: 166063...
So arrays are optimized! Which is fortunate...
Christoph's demonstration didn't impress me. My conclusion would be more that strings that can be interpreted as numbers are treated as such, which go along with the quoted formula...
So my interpretation of your results is that the array is behaving like a fast array with numerical indices when feed with these (with perhaps a behavior of associative array on sparse values, ie. some isolated big indices), but as an object, it still has the normal handling of properties. But these properties aren't handled in the array part, hence the result you got with join().
[EDIT] I added some loops, following Christoph's idea.
On FF3, I get: With array: 92 With s array: 93 With object(i): 243 With s object: 194 With i object: 125 (perfs vary between runs, but are roughly consistent).
I am not super-convinced of this integer -> string -> integer round-trip, not even that ECMA requests this sequence. The way I read it is: is the property is a string and can be interpreted as integer, then it is treated as such.
Of course, the only sure way to know would be to look at an implementation...
I notice with interest that plain objects getting an integer property or a property that can be transformed to an integer are somehow optimized. Perhaps because lot of JS programmers used plain objects as arrays, so implementers judged interesting to optimize this case.