JavaScriptのsortは必ずしも安定ではないのを覚えといてね

配列要素はソート (並べ替え) される。ソートは必ずしも安定的ではない(つまり、等価と比較された要素が元の順で残るとは限らない). comparefn が undefined でないならば、それは 2 個の引数 x と y を受け付け、 x < y ならば負の値、 x = y ならば 0、 x > y ならば正の値を返す関数であるべきである。

15.4 Array オブジェクト (Array Objects)

安定であると仮定した実装はしないでください。(複数列でのテーブルソートなど注意)

以上。

これより先は脱線なので読み飛ばしてもらってかまいません。

脱線1

このページを開いたとき、FirefoxSafari ではタグがアルファベット順にソートされる。(たぶん IE も)

ChromeOpera では変な順にソートされる。

http://l.yimg.com/hr/1125/js/del-tagrolls.js

            if (o.sort == 'alpha') {
                tags_out.sort(function(a,b) {
                    return ( (a.name.toLowerCase > b.name.toLowerCase) ? 1 : (a.name.toLowerCase < b.name.toLowerCase) ? -1 : 0 );
                });
            }

toLowerCase() の括弧が抜けているため、比較関数が全部 0 を返してしまっているのが原因。安定ソートのブラウザでしか確認してないんだろうなあ…

以上は既に Delicious に報告してある。

脱線2

javascript:
function comparefn(a,b){return 0}; // 0, false, null, undefined, NaN
var array=[1,2,3,4,5,6,7,8,9,0];
array = array.sort(comparefn);
alert(array);

comparefn が 0, false, null, undefined, NaN を返すとき、各ブラウザでどうなるか実験。

(comparefn は NaN 以外の Number 型を返さないといけません。念のため)

Firefox (3.5系)
0 1,2,3,4,5,6,7,8,9,0
false 1,2,3,4,5,6,7,8,9,0
null 1,2,3,4,5,6,7,8,9,0
undefined 1,2,3,4,5,6,7,8,9,0
NaN 1,2,3,4,5,6,7,8,9,0
Safari (4系)
0 1,2,3,4,5,6,7,8,9,0
false 1,2,3,4,5,6,7,8,9,0
null 1,2,3,4,5,6,7,8,9,0
undefined 1,2,3,4,5,6,7,8,9,0
NaN 1,2,3,4,5,6,7,8,9,0
Chrimium (3系)
0 2,4,6,8,0,9,7,5,3,1
false 2,4,6,8,0,9,7,5,3,1
null 0,9,8,7,6,5,4,3,2,1
undefined 0,9,8,7,6,5,4,3,2,1
NaN 0,9,8,7,6,5,4,3,2,1
Opera (10系)
0 1,2,3,4,8,0,7,9,5,6
false 1,2,3,4,8,0,7,9,5,6
null 1,2,3,4,8,0,7,9,5,6
undefined 6,0,7,3,9,8,2,1,5,4
NaN 6,0,7,3,9,8,2,1,5,4


IE では確認してないけど、たぶん Chrome の登場までは Opera だけが非安定だったのだと思う。

だから、安定であると仮定したことに起因するバグは、けっこうある気がする。