JavaScriptでオブジェクトのキー配列取得したい…
そういう時は Object.keys() を使うのが鉄板です。
でもある時こんな疑問が浮かびました。
- 返ってくるキーの順序は?
- 定義した順番に返ってくるのか
- それとも別の規則性がある?
キー配列の順序が気になったので、
Object.keys() のキー順序について調べました。
このページの目次
Object.keys()の基本的な概要・使い方
これは調べればいくらでも出てきます。
一番確実なのはMDNリファレンスを見ることですね。
▼ MDNにおけるObject.keys()の概要
Object.keys() メソッドは、指定されたオブジェクトが持つプロパティの 名前の配列を、通常のループで取得するのと同じ順序で返します。
引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
▼ 基本的な使い方コード例
1 2 3 4 5 6 7 8 9 |
const nameToHexMap = { 'red': '#ff0000', 'green': '#00ff00', 'blue': '#0000ff' }; const keys = Object.keys(nameToHexMap); console.log(keys); /// => [red, green, blue] |
このようなオブジェクトのキー配列を返すメソッド
使い方の注意点としてはオブジェクトに対して直接呼び出せないため、 Object.keys() に直接オブジェクトを渡すような使い方をします。
そして解説で気になるのが次の箇所。
「通常のループで取得するのと同じ順序で」
ここが少し分からない所でした。
Object.keys()は配列に対しても使える
そしてこの Object.keys() の面白い性質?について。
それは配列に対しても使えるってことです。
▼ このようなコードで考えてみる
1 2 3 4 |
const colors = ['red', 'green', 'blue']; const indexes = Object.keys(colors); console.log('indexes : ', indexes); /// => ['0', '1', '2'] |
インデックス番号の配列が返ってきました。
つまりJavaScript内部では ['red', 'green', 'blue'] というのは {0:'red', 1:'green', 2:'blue'} というオブジェクトと等価(?)になってます。
これが Object.keys() のキー順序に影響を与えます。
数字キーを含むオブジェクトは順序通りではない
ということで Object.keys() の順序について。
基本的には定義した順序でキー配列が返ってきます。
でも前述したように数字キーの場合は例外です。
▼ 例えばこんなオブジェクトで試してみる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/// 数字キーを持つオブジェクト const idToNameMap = { 107: 'purple', 104: 'green', 103: 'yellow', 106: 'indigo', 101: 'red', 105: 'blue', 102: 'orange' }; /// 数字で解釈されるキーでも同様 const idToNameMap = { '107': 'purple', '104': 'green', '103': 'yellow', '106': 'indigo', '101': 'red', '105': 'blue', '102': 'orange' }; const keys = Object.keys(idToNameMap); console.log(keys); |
▼ 上記コードの出力結果
1 2 3 4 5 6 7 8 9 |
[ '101', '102', '103', '104', '105', '106', '107' ] |
こういう感じでキーの順序は保持されてません。
というより配列として解釈された感じです。
だから数字に解釈されるキーを含む場合…
- キー配列は定義した順序にならない
- 数字キーは昇順で並び替えされる
こういう性質があることに要注意です。
文字列キーの場合は順序は保持される
一方の普通の文字列キーなら順序はキープされます。
▼ このようなコードを試してみる
1 2 3 4 5 6 7 8 9 10 11 12 |
const nameToIdMap = { purple: 107, green: 104, yellow: 103, indigo: 106, red: 101, blue: 105, orange: 102 }; const keys = Object.keys(nameToIdMap); console.log(keys); |
▼ 上記コードの出力結果
1 2 3 4 5 6 7 8 9 |
[ 'purple', 'green', 'yellow', 'indigo', 'red', 'blue', 'orange' ] |
文字列キーはそのまんまの順序が保持されます。
昇順で並び替えなんてされません、期待通りの動作。
だから文字列キーだけを含むオブジェクトなら、
返ってくるキー配列の順序は心配しなくていいってこと。
数字キーと文字列キーを両方含む時の順序は…?
数字キーと文字列キーの両方を含むオブジェクト
その場合どうなるかは気になるところです。
▼ だからこんなコードで確かめてみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const obj = { '8': 'eight', 'five': 5, '3': 'three', '7': 'seven', 'two': 2, 'one': 1, '4': 'four', '6': 'six', 'nine': 9 }; const keys = Object.keys(obj); console.log(keys); |
▼ 上記コードの出力結果
1 2 3 4 |
[ '3', '4', '6', '7', '8', 'five', 'two', 'one', 'nine' ] |
このような結果になりました。
もし Object.keys() が常に順序通りと思ってるなら…
意図しない結果を引き起こすかもしれません。
返ってくるキーの順序はこうなる
結論としてはこうなります。
- 数字キーが順序的には優先される
- 数字キーは昇順として並び替えられる
- 文字列キーは順序的に数字キーの後
- 文字列キー同士の並びは影響されない
この挙動を知らないと、思わぬミスを引き起こします。
以上、 Object.keys() の順序に注意が必要って話でした。
もしおかしな点があればご指摘ください。ではまた