テック技報最新号へ →
コード

JS: オブジェクトのキーの順番は「整数っぽいキーが先・昇順」

Object.keys・for...in・JSON.stringify などが返すキーの順番は、ただの追加順ではない。配列の添字として有効な整数のキー(0〜4294967294)が先に数値の昇順で並び、そのあとに残りの文字列キーが追加順で並ぶ。

@xah_lee · 2026-11-11
#javascript#object#map

困る場面

ID をキーにしたオブジェクトで「サーバーから返ってきた順」や「追加した順」を保ちたいときに、勝手に並べ替わる。

js
const byId = {};
byId["30"] = "c";
byId["b"]  = "x";
byId["10"] = "a";
byId["2"]  = "b";
Object.keys(byId); // ["2", "10", "30", "b"]

ルール(仕様の OrdinaryOwnPropertyKeys)

  1. 配列の添字になれるキー("0"〜"4294967294"、つまり 2^32 − 2 まで)を数値の昇順
  2. それ以外の文字列キーを追加した順
  3. Symbol キーを追加した順(Object.keys や for...in には出ず、Reflect.ownKeys などで見える)

"4294967295"(2^32 − 1)以上、"-1"、"01"、"1.5" は「整数っぽく」見えても文字列キー扱いで、追加順に並ぶ。

js
Object.keys({ b: 1, "4294967295": 2, "4294967294": 3, a: 4, "01": 5 });
// ["4294967294", "b", "4294967295", "a", "01"]

対策

  • 順番に意味があるなら Map を使う。Map はキーの型に関係なく追加順を保つ。
  • オブジェクトのままにするなら、順番は別に配列(ids: string[])で持つ。
  • どうしてもキーで済ませたいなら "id_30" のように接頭辞を付けて整数扱いを避ける。

注意点

  • JSON.parse の結果も同じルールで並ぶので、API が返した JSON オブジェクトのキー順はそのまま信用しない。
  • この順番は ES2015 以降の仕様で決まっていて、for...in と Object.keys の順も ES2020 で揃えられた。

出典

  • @xah_lee(js tip. order of properties, with a magic number 4294967294)
X の元の投稿を開く