dhtml said:
Can you elaborate on that?
Array.prototype.sort's default comparison is required to sort the
array elements so that the "undefined" value is greater than all
other values, but less than no value at all. I.e., if the array
doesn't have a value at an index at all (as opposted to having
a value that is undefined), then the sorted array will too, and
it will have those at the end.
Or, to quote 15.4.4.11:
There must be some mathematical permutation p of the nonnegative
integers less than Result(2), such that for every nonnegative integer
j less than Result(2), if property old[j] existed, then new[p(j)] is
exactly the same value as old[j],. but if property old[j] did not
exist, then new[p(j)] does not exist.
Then for all nonnegative integers j and k, each less than Result(2),
if SortCompare(j,k)<0 (see SortCompare below), then p(j)< p(k).
and SortCompare(j,k) (where j and k are indices) is defined as:
1. Call ToString(j).
2. Call ToString(k).
3. If this object does not have a property named by Result(1), and this object does not have a
property named by Result(2), return +0.
4. If this object does not have a property named by Result(1), return 1.
5. If this object does not have a property named by Result(2), return -1.
6. Call the [[Get]] method of this object with argument Result(1).
7. Call the [[Get]] method of this object with argument Result(2).
8. Let x be Result(6).
9. Let y be Result(7).
10. If x and y are both undefined,return +0.
11. If x is undefined,return 1.
12. If y is undefined,return -1.
13. If the argument comparefn is undefined, goto step 16.
14. Call comparefn with arguments x and y.
15. Return Result(14).
16. Call ToString(x).
17. Call ToString(y).
18. If Result(16) < Result(17), return -1.
19. If Result(16) > Result(17), return 1.
20. Return +0.
I.e., step 3..5 means that missing properties are sorted last,
step 6..12 means that undefined are sorted just before those,
and for all other values, their string representation is compared.
Example: The array:
var a = [42,NaN,0,"",,false,undefined,null,,true]
has a length of 10, but only 9 elements. The expressions
(4 in a)
and
(8 in a)
both evaluate to false.
Sorting it using
a.sort()
should give the equivalent of
["",0,42,NaN,false,null,true,undefined,,,]
Try the following in different browsers:
var a = [42,NaN,0,"",,false,undefined,null,,true]
a.sort();
function prettyArray(arr) {
var res = [];
res.length = arr.length;
for(var i = 0; i < arr.length; i++) {
if (i in arr) {
var pretty;
if (typeof arr
== "string") {
res = '"' + arr + '"';
} else {
res = String(arr);
}
}
}
if (!((arr.length-1) in arr)) { res.length++; }
return "[" + res.join(",") + "]";
}
alert(prettyArray(a));
In Opera, one of the missing elements is converted to an existing
element with value "undefined":
alert(8 in a); // Opera: true!
In Firefox 3, both missing elements are converted to undefined values:
alert(8 in a); // FF3: true!
alert(9 in a); // FF3: true!
IE 7 actually removes the undefined value:
alert(7 in a); // IE7: false!
(It doesn't help that IE fails to ignore a final comma in array literals:
[42,].length == 2 // IE7. Should be 1
)
Safari actually appears to sort it correctly.
/L