オブジェクトには map() も filter() もありません。
配列にしてから配列のメソッドを使い、必要ならオブジェクトに戻します。
| 欲しいもの | 使うもの |
|---|---|
| 鍵だけ | Object.keys() |
| 値だけ | Object.values() |
| 鍵と値の組 | Object.entries() |
回す
entries() と分割代入を組み合わせるのが定石です。
[subject, score] は、['国語', 80] という配列を2つの名前に分ける書き方です。
→ 入れ子のオブジェクトを安全に扱う
変換する
entries() で配列にし、配列のメソッドを通し、fromEntries() で戻します。
Math.round() を挟んでいるのは、100 * 1.1 が 110.00000000000001 になるためです。理由は「なぜ 0.1 + 0.2 は 0.30000000000000004 になるのか」にあります。
絞り込みも同じ形です。
const base = { shared: 1 };
const child = Object.create(base);
child.own = 2;
const seen = [];
for (const key in child) {
seen.push(key);
}
console.log(seen);
console.log(Object.keys(child));[, price] は「1つ目は使わない」という書き方です。読み飛ばす意図が伝わります。
この「配列にして、戻す」形を覚えれば、配列のメソッドが全部使えます。 → 配列を変換する・絞り込む
合計や件数を出す
件数は Object.keys(obj).length です。配列と違って obj.length はありません。
鍵の並び順には決まりがある
「入れた順」だと思っていると、ずれることがあります。
整数に見える鍵が、先に、小さい順に並びます。 そのあとが入れた順です。
b より先に 1 と 2 が来ています。
並び順を当てにするコードは、鍵に数字を使った瞬間に壊れます。
順番を守りたいなら Map を使ってください。Map は必ず入れた順です。
→ Map と Set
for...in を使わない
回す書き方には for...in もありますが、勧めません。
for...in は受け継いだ鍵まで拾います。shared は自分で書いていません。
Object.keys() は自分の分だけを返します。
for...in を書くくらいなら、Object.entries() を使ってください。
for...in は配列にも使えますが、そちらでは添字が文字列になるうえ、順序の保証も弱くなります。配列は for...of です。
鍵で引くだけなら回さない
全部を回す前に、そもそも回す必要があるかを考えてください。
オブジェクトは鍵で1つ引くのが得意な形です。
全部を順に見たいなら、最初から配列や Map のほうが向いています。
まとめ
- オブジェクトに
map()もfilter()も無い Object.entries()で配列にし、配列のメソッドを通し、fromEntries()で戻す- 件数は
Object.keys(obj).length。obj.lengthは無い - 整数に見える鍵が先に、小さい順に並ぶ。 順番を守るなら
Map for...inは受け継いだ鍵まで拾う。Object.entries()を使う- そもそも回す必要があるかを先に考える
この連載はここまで
オブジェクトを作り、深いところから安全に取り出し、まとめて変換するところまで来ました。 ここから先は、必要になったときに引ける形でまとめてあります。
- Object.keys() / values() / entries()
…
nullを渡したときの挙動、配列や文字列に使った結果 - オブジェクトを結合する
… 1段しか複製されない理由、
structuredClone()との違い - Map と Set … 鍵に文字列以外を使いたくなったとき
- 配列をキーごとにまとめる … 配列からオブジェクトを組み立てる