Object.keys と Object.values で集計する
Object.keys と Object.values で集計する とは
Object.keys / values / entries でオブジェクトを配列化し、reduce で合計を求める頻出パターンを学ぶ。
Object.keys と Object.values で集計する
オブジェクトをループするとき、for...in でキーを回す書き方もありますが、現代の主流は Object.keys / values / entries で配列に変換してから map や reduce を使う書き方です。API で受け取った集計データから合計を出す、フォームの状態を配列化して検証する、といったシーンで毎日のように使う技です。
オブジェクトをループするときは 配列化してから高階関数 に流すのが最も読みやすい。
3 つの基本メソッド
オブジェクトを配列化する static メソッドは次の 3 つです。
Object.keys(obj)はキーの配列を返しますObject.values(obj)は値の配列を返しますObject.entries(obj)は[key, value]のペア配列を返します
JavaScript
const scores = { math: 80, english: 90, science: 70 };
console.log(Object.keys(scores)); // ["math", "english", "science"]
console.log(Object.values(scores)); // [80, 90, 70]
console.log(Object.entries(scores));
// [["math", 80], ["english", 90], ["science", 70]]配列化されればこっちのもの。map、filter、reduce、forEach がそのまま使えます。
values + reduce で合計
オブジェクトの数値合計を求めるのは、Object.values と reduce の黄金コンビです。
JavaScript
const scores = { math: 80, english: 90, science: 70 };
const total = Object.values(scores).reduce((acc, v) => acc + v, 0);
console.log(total); // 240初期値 0 を忘れないように。空オブジェクトのときも 0 を返してくれます。
JavaScript
const empty = {};
const total = Object.values(empty).reduce((acc, v) => acc + v, 0);
console.log(total); // 0
reduceの初期値を省略すると、空配列で TypeError になる。集計系では必ず初期値を書く。
entries で key と value の両方を扱う
キーと値の両方が欲しいときは Object.entries + 分割代入が最強です。
JavaScript
for (const [key, value] of Object.entries(scores)) {
console.log(`${key}: ${value}`);
}配列メソッドにも自然に渡せます。
JavaScript
const report = Object.entries(scores)
.map(([k, v]) => `${k} は ${v} 点`)
.join("、");
console.log(report);
// "math は 80 点、english は 90 点、science は 70 点"動きを追ってみる
図のとおり、オブジェクトをまず配列化し、その後に配列メソッドで処理するという流れが基本のフローです。
Object.fromEntries で逆変換
entries の逆操作が Object.fromEntries です。[key, value] ペアの配列をオブジェクトに戻します。これを使うと「キー単位で変換 → 再度オブジェクトに」というパイプラインが書けます。
JavaScript
const scores = { math: 80, english: 90 };
const doubled = Object.fromEntries(
Object.entries(scores).map(([k, v]) => [k, v * 2]),
);
console.log(doubled); // { math: 160, english: 180 }
entries → map → fromEntriesは オブジェクト版の map として頻出する。覚えておくとコードが一気に短くなる。
よくある間違い
第 1 に、Object.values を reduce する際に初期値を忘れると、空オブジェクトで例外を出します。reduce((a, b) => a + b) ではなく reduce((a, b) => a + b, 0) と書きます。第 2 に、for...in はプロトタイプチェーンも舐めるので、安全のために Object.hasOwn(obj, key) を使うか、最初から Object.keys で配列化する方が安全です。第 3 に、Object.keys の戻り順は 挿入順 が保証されますが、数値文字列のキーは小さい順に並ぶという仕様もあります。文字列キーだけ使うなら気にしなくて OK です。
やってみよう
数値プロパティだけを持つオブジェクト obj を受け取り、すべての値の合計を返す sumValues 関数を書きましょう。return Object.values(obj).reduce((a, b) => a + b, 0) の 1 行で完成です。空オブジェクトでも 0 を返すか、テストで確認してみてください。応用として Object.entries を使い、特定のキーだけ合計するバリエーションも面白いです。
よくある質問
Q. ブラウザと Node.js で動作は変わりますか?
A. JavaScript の構文・組み込み機能(配列・文字列・Promise 等)はどちらでも同じです。違いは DOM API(ブラウザ専用)と fs などのファイル系(Node 専用)など、実行環境固有の機能です。コアロジックは両方で動くため、テストもしやすくなります。
Q. ES6 以降の新機能は使っても大丈夫ですか?
A. 現代のブラウザ・Node.js は ES2020 以降の機能をほぼサポートしています。古い IE 等を対象にする必要が無ければ、let/const、アロー関数、分割代入、async/await を積極的に使ってください。トランスパイル(Babel/Vite)が必要なケースは年々減っています。
Q. TypeScript に進む価値はありますか?
A. 型情報があるとリファクタやエディタ補完が劇的に効くため、規模が大きくなるなら TypeScript への移行を強くおすすめします。最初は any を許容しつつ徐々に型を付ければ、JS の知識をそのまま活かせます。
次のレッスン
次は reduce でキー別にグルーピングする で、Object を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- keys と values の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. keys と values とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- Object.values で値の配列を取得すること
- Array.prototype.reduce で合計すること
- 初期値 0 を必ず渡すこと
入出力例
test-cases.txt
sumValues({"english":90,"math":80,"science":70}) → 240
sumValues({"only":100}) → 100
sumValues({}) → 0
sumValues({"a":10,"b":0,"c":-5}) → 5