要点
- 文字と数字が混ざるキーでは、PythonとJavaScriptで列挙順が異なった(出典: 自社の実測・2026-10-26)。
b, c, aという文字キーだけの例では、両方とも追加順を保った(出典: 自社の実測・2026-10-26)。- JavaScriptで
10, 2, 1の順に追加したキーは、1, 2, 10の順に並んだ(出典: 自社の実測・2026-10-26)。 - 表示順を制御する場合は、キーとは別に配列で順序を保持する対処がある(出典: https://tc39.es/ecma262/#sec-ordinaryownpropertykeys)。
同じ順番で追加しても、同じ順番では取り出せない
キーの列挙順とは、オブジェクトや辞書からキーを取り出すときに並ぶ順序のことだ。
Pythonの辞書とJavaScriptのオブジェクトに、同じキーを同じ順番で追加する。この操作だけを見ると、取り出す順番も同じだと考えたくなる。しかし、今回の記録では、文字と数字に見える文字列が混ざる場合に違いが出た。
追加した順番は、どちらもb、2、a、1である。Pythonではそのままの順番で返った。一方、JavaScriptでは1と2が先に並び、続いてbとaが返った。JavaScript側の記録をそのまま示す。
const o = {};
o['b'] = 1;
o['2'] = 2;
o['a'] = 3;
o['1'] = 4;
console.log(Object.keys(o));
// [ '1', '2', 'b', 'a' ]
ここで注意したいのは、'2'や'1'を引用符で囲んでいる点だ。文字列としてキーを書いていても、この例では文字キーのbやaと同じ扱いにはならなかった。「文字列で指定したから追加順になる」という判断は、この結果と一致しない。
実測環境はPython 3.9.0とNode.js v22.23.4。以下の実測結果も、この環境で記録されたものを扱う。
出典: 自社の実測(2026-10-26)
公式仕様はキーの種類を分けている
ECMAScript仕様書の「OrdinaryOwnPropertyKeys」は、キーをひとまとめに追加順で列挙する規定ではない。素材に記録された仕様の説明では、まず「array index」に当たるキーを昇順で列挙し、その後に残りの文字列キーを作成順で列挙するとされている。
したがって、最初の例は「すべてのキーが並べ替えられた」と読むと不正確になる。1と2は数値として昇順に並んだが、後ろの文字キーはb、aという追加順を保っている。キーの種類によって、適用される順序が分かれている。
出典: https://tc39.es/ecma262/#sec-ordinaryownpropertykeys (取得日 2026-10-26)
一方、Python公式ドキュメントのdictの説明には、次の記述がある。
Dictionaries preserve insertion order
出典: https://docs.python.org/3/library/stdtypes.html#dict (取得日は素材に記載なし)
Pythonの辞書が挿入順を保つことは、Python 3.7以降の仕様として素材にも記載されている。今回のPythonの結果は、その説明に沿うものだった。
ただし、「数字に見える」という表現だけで、あらゆる文字列キーを分類することはできない。今回確かめたのは、記録にある正の整数を表したキーである。仕様の用語と、見た目についての説明を区別して読む必要がある。
文字キーと数字に見えるキーを比較する
実測結果を、追加したキーの種類ごとに並べる。表の順序は素材の記録に合わせたものであり、未測定の組み合わせは補っていない。
| 対象 | キーを追加した順番 | 取り出した順番 | 記録から分かること |
|---|---|---|---|
| Pythonの辞書 | b, 2, a, 1 |
b, 2, a, 1 |
混在していても追加順を保った |
| JavaScriptのオブジェクト | b, 2, a, 1 |
1, 2, b, a |
数字に見えるキーが先に並んだ |
| Pythonの辞書 | b, c, a |
b, c, a |
文字キーは追加順を保った |
| JavaScriptのオブジェクト | b, c, a |
b, c, a |
文字キーは追加順を保った |
| JavaScriptのオブジェクト | 10, 2, 1 |
1, 2, 10 |
数値として昇順に並んだ |
| JavaScriptの配列 | 5, 1 |
1, 5 |
設定順よりインデックスの昇順が優先された |
文字キーだけの行では、PythonとJavaScriptの結果に差がない。この例だけを確認すると、数字に見えるキーが混ざったときの違いは分からない。
また、10、2、1の例は、並べ方を区別するために役立つ。結果は1、2、10であり、文字列としての辞書順である1、10、2ではなかった。単に「ソートされる」と説明するより、数値としての大小で並んだと捉えるほうが、記録に忠実だ。
配列でも、インデックス5を先に設定し、次に1を設定したところ、Object.keysでは1が先に出ている。追加した順番と取り出す順番の違いは、普通のオブジェクトだけでなく、要素を飛び飛びに設定した配列でも確認された。
出典: 自社の実測(2026-10-26)
追加順を使うか、表示用の順序を別に持つか
用途を考えるときは、キーが何を表すかと、どの順番で表示したいかを分けて整理するとよい。
Pythonの辞書では、今回の混在例でも追加順が保たれた。対してJavaScriptのオブジェクトでは、商品番号やIDのような数字に見える文字列をキーにすると、登録順と列挙順が一致しない場合がある。Python側で追加順に依存していた処理をJavaScriptへ移すなら、この差は確認する対象になる。
素材で挙げられている対処は、順序を別の配列で保持する方法と、キーの先頭に数字以外の文字を付ける方法だ。表示順そのものを制御したいなら、別の配列に順序を持たせる方法が選択肢になる。キーの表記を変更できるなら、数字に見えないキーにする方法も検討できる。
ただし、これらの対処を適用した実行結果は今回の記録にはない。比較表で確認済みなのは、文字キーだけの例、数字に見えるキーを含む例、配列の例である。対処案と実測済みの結果を混ぜて読まないことが大切だ。
また、負の数や小数を表したキーの分類は測っていない。MapやSetの順序も今回の比較には含まれない。これらについて、今回の結果だけから同じ順序になると断定することはできない。
自分の環境で確かめる手順
PythonとNode.jsを使える環境では、次のコマンドで版を確認し、同じ順番でキーを追加した場合の列挙順を比較できる。以下は読者が実行するための手順であり、新たに測定した結果ではない。
python3 --version
node --version
python3 -c "d = {}; d['b'] = 1; d['2'] = 2; d['a'] = 3; d['1'] = 4; print(list(d.keys()))"
node -e "const o = {}; o['b'] = 1; o['2'] = 2; o['a'] = 3; o['1'] = 4; console.log(Object.keys(o));"
確認する点は、数字に見えるキーがどこに並ぶかと、文字キー同士の順番がどうなるかである。単に出力が違うかを見るだけでなく、1と2の位置、bとaの前後関係をそれぞれ見ると、仕様が分けている順序を確かめられる。
続けて文字キーだけの例と比べれば、追加順が一致する場合と、一致しない場合を区別できる。自分の処理が必要としているのが登録順なのか、数値順なのかを決めたうえで、キーの列挙結果をそのまま使えるか判断したい。

コメント