オブジェクトのキーの順序
上記リンク先の手法は、新たなオブジェクトにキーを配列に入れてソートした後、その順にプロパティ値として入れる方法だ。が、この方法では完全にソートすることはできない。
仕様的にも実装的にも無理である。
仕様的に
- ECMAScript 5th 仕様には、プロパティ列挙の順序は書かれていない
- ECMAScript 6th Draft には、9.1.11 [[Enumerate]] () に
The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.
と明記されている。
要するに実装まかせであり、仕様として順序は保証していない。
実装的に
上記のように仕様はないとはいえ、皆似たような順序になるよう調整されている。
概ね、strawman:enumeration [ES Wiki]の下部に載っているような順序になる。
- Uint32範囲内の整数になるキー値なら、Index値として順にソートされ、先にならぶ
- その他は定義された順
v8(Chrome), Chakra(IE11), JSC(Safari) はそんな感じ。ただし、微妙にずれがある。
v8 は 0 - 0xFFFFFFFF(2^32-1) で、Chakra, JSCは 0 - 0xFFFFFFFF-1(2^32-2) がIndex値として捉えられる範囲っぽい。
SpiderMonkey(Firefox)の謎挙動
上記では挙げなかったSpiderMonkeyであるが…。
999と1000が境界っぽく、意味不明である。(Firefox25調べ)
var obj = { "a":"", 1:"", 100:"", 999:"", 3:"" }; for (var key in obj){ console.log(key); } // 1 // 3 // 100 // 999 // a
だが、1000 以上になると、Index値としての対象にならない模様。
var obj = { "a":"", 1:"", 100:"", 1000:"", 3:"" }; for (var key in obj){ console.log(key); } // 1 // 3 // 100 // a // 1000
話が脱線したが、ともかく、整数に変換可能なキーは勝手にソートされるため、オブジェクトに入れ直す手法は完全ではない。