2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オブジェクトをループする3つの書き方と、for...in を配列に使ってはいけない理由

2
Posted at

{ name: "太郎", age: 20 } のようなオブジェクトの中身を1つずつ取り出したいとき、書き方が3つあります。どれも動きますが、挙動と向き不向きが違うので整理します。

1. for...in

const user = { name: "太郎", age: 20 };

for (const key in user) {
  console.log(key, user[key]);
}
// name 太郎
// age 20

一番古くからある書き方です。変数にはキー(プロパティ名)が入るので、値は user[key] で取り出します。

2. Object.keys() + for...of

for (const key of Object.keys(user)) {
  console.log(key, user[key]);
}

Object.keys(user) は ["name", "age"] というキーの配列を返します。配列になるので、for...of で回すことも、map や filter につなげることもできます。

3. Object.entries() + 分割代入

for (const [key, value] of Object.entries(user)) {
  console.log(key, value);
}

Object.entries(user) は [["name", "太郎"], ["age", 20]] という「キーと値のペアの配列」を返します。分割代入で [key, value] と受ければ、user[key] と書き直す手間が無くなります。値だけ欲しいなら Object.values(user) もあります。

for...in の罠①: プロトタイプ経由のプロパティまで拾う

3つとも普通のオブジェクトなら同じ結果ですが、for...in だけは「そのオブジェクト自身のプロパティ」以外も列挙します。

Object.prototype.extra = "x"; // 誰かがこういうことをしていると…

const o = { a: 1 };

const inKeys = [];
for (const k in o) inKeys.push(k);

console.log(inKeys);          // [ 'a', 'extra' ]  ← 自分で定義していない extra が混ざる
console.log(Object.keys(o));  // [ 'a' ]           ← 自身のプロパティだけ

delete Object.prototype.extra; // 後片付け(これを忘れると、この後のコードにも extra が混ざります)

for...in はプロトタイプチェーン(継承元)をたどって、列挙可能なプロパティをすべて拾います。自分のコードで Object.prototype を触ることはまず無いと思いますが、読み込んだライブラリが触っている可能性はゼロではなく、その場合に for...in だけが影響を受けます。Object.keys / Object.entries は自身のプロパティしか見ないので、この問題が起きません。

for...in の罠②: 配列に使うとインデックスが文字列になる

for (const i in ["a", "b"]) {
  console.log(typeof i, i);
}
// string 0
// string 1

配列に for...in を使うと、変数に入るのは要素ではなくインデックスで、しかも文字列です。i + 1 と書いたつもりが "0" + 1 = "01" という文字列結合になる、という事故につながります。配列を回すときは for...of(要素が入る)か forEach / map を使ってください。for...in はオブジェクト専用、と覚えておくのが安全です。

補足: 順序は「挿入順、ただし整数っぽいキーは先頭に昇順」

console.log(Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }));
// [ '1', '2', 'b', 'a' ]

Object.keys / Object.entries / for...in のいずれも、0以上の整数として解釈できるキー("1", "2" など。"-1" や "01" は文字列扱い)が先に昇順で並び、その後に文字列キーが定義順で並びます。「定義した順に出てくるだろう」と思っていると、数値キーが混ざったときに順番がずれるので、順序に意味があるデータは配列で持つのが無難です。

まとめ

  • オブジェクトを回すなら Object.entries() + 分割代入が読みやすく、値の取り出しも1手で済む
  • for...in はプロトタイプ経由のプロパティまで列挙する。Object.keys / Object.entries は自身のプロパティだけ
  • 配列に for...in は使わない(インデックスが文字列で入る)。配列は for...of / forEach / map
  • キーの順序は「整数っぽいキーが先頭に昇順→残りは定義順」

(上記の出力はすべて Node.js v24 で実行して確認しています)


未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全24セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md と学習モード(learner / developer)の設計までセットで含みます。

※ 中上級者には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?