メインコンテンツまでスキップ

オブジェクトをループする方法

JavaScript・TypeScriptでオブジェクトのプロパティをループする方法を説明します。

for-in文

JavaScriptでオブジェクトをループする古くからある方法はfor-in文を使うものです。

js
const foo = { a: 1, b: 2, c: 3 };
for (const prop in foo) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3 の順で出力される
}
js
const foo = { a: 1, b: 2, c: 3 };
for (const prop in foo) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3 の順で出力される
}

for-in文ではhasOwnPropertyを使おう

JavaScriptのオブジェクトには元になるプロトタイプがあります。たとえば、オブジェクトリテラルであれば、Object.prototypeがプロトタイプになります。

js
const foo = { a: 1, b: 2, c: 3 };
console.log(Object.getPrototypeOf(foo) === Object.prototype);
true
js
const foo = { a: 1, b: 2, c: 3 };
console.log(Object.getPrototypeOf(foo) === Object.prototype);
true

Object.prototypeを変更するとその影響は、このプロトタイプを持つすべてのオブジェクトに影響します。

js
const foo = { a: 1 };
const date = new Date();
const arr = [1, 2, 3];
 
// どのオブジェクトもhiプロパティが無いことを確認
console.log(foo.hi, date.hi, arr.hi);
undefined undefined undefined
 
// プロトタイプにプロパティを追加する
Object.prototype.hi = "Hi!";
 
// どのオブジェクトもhiプロパティを持つようになる
console.log(foo.hi, date.hi, arr.hi);
Hi! Hi! Hi!
js
const foo = { a: 1 };
const date = new Date();
const arr = [1, 2, 3];
 
// どのオブジェクトもhiプロパティが無いことを確認
console.log(foo.hi, date.hi, arr.hi);
undefined undefined undefined
 
// プロトタイプにプロパティを追加する
Object.prototype.hi = "Hi!";
 
// どのオブジェクトもhiプロパティを持つようになる
console.log(foo.hi, date.hi, arr.hi);
Hi! Hi! Hi!

for-in文はプロトタイプのプロパティも含めてループする仕様があります。そのため、プロトタイプが変更されると、意図しないところでfor-inのループ回数が変わることがあります。

js
const foo = { a: 1, b: 2, c: 3 };
Object.prototype.hi = "Hi!";
for (const prop in foo) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3
// hi Hi! の順で出力される
}
js
const foo = { a: 1, b: 2, c: 3 };
Object.prototype.hi = "Hi!";
for (const prop in foo) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3
// hi Hi! の順で出力される
}

したがって、for-inで反復処理を書く場合は、hasOwnPropertyでプロパティがプロトタイプのものでないことをチェックしたほうが安全です。

js
const foo = { a: 1, b: 2, c: 3 };
Object.prototype.hi = "Hi!";
for (const prop in foo) {
if (Object.prototype.hasOwnProperty.call(foo, prop)) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3 の順で出力される
}
}
js
const foo = { a: 1, b: 2, c: 3 };
Object.prototype.hi = "Hi!";
for (const prop in foo) {
if (Object.prototype.hasOwnProperty.call(foo, prop)) {
console.log(prop, foo[prop]);
// a 1
// b 2
// c 3 の順で出力される
}
}

Object.entries

Object.entriesの戻り値をfor-of文でループする方法もあります。

ts
const foo = { a: 1, b: 2, c: 3 };
for (const [key, value] of Object.entries(foo)) {
console.log(key, value);
// a 1
// b 2
// c 3 の順で出力される
}
ts
const foo = { a: 1, b: 2, c: 3 };
for (const [key, value] of Object.entries(foo)) {
console.log(key, value);
// a 1
// b 2
// c 3 の順で出力される
}

for-in文と異なり、hasOwnPropertyのチェックが不要です。

Object.keys

プロパティのキーだけを反復処理する場合は、Object.keyの戻り値をfor-of文でループする方法があります。

ts
const foo = { a: 1, b: 2, c: 3 };
for (const key of Object.keys(foo)) {
console.log(key);
// a
// b
// c の順で出力される
}
ts
const foo = { a: 1, b: 2, c: 3 };
for (const key of Object.keys(foo)) {
console.log(key);
// a
// b
// c の順で出力される
}

for-in文と異なり、hasOwnPropertyのチェックが不要です。

Object.values

プロパティの値だけを反復処理する場合は、Object.valuesの戻り値をfor-of文でループする方法があります。

ts
const foo = { a: 1, b: 2, c: 3 };
for (const value of Object.values(foo)) {
console.log(value);
// 1
// 2
// 3 の順で出力される
}
ts
const foo = { a: 1, b: 2, c: 3 };
for (const value of Object.values(foo)) {
console.log(value);
// 1
// 2
// 3 の順で出力される
}

for-in文と異なり、hasOwnPropertyのチェックが不要です。

学びをシェアする

JavaScriptやTypeScriptのオブジェクトプロパティをループするには次の方法がある。

1️⃣ for-in文
2️⃣ for-of文 + Object.entries()
3️⃣ for-of文 + Object.keys()
4️⃣ for-of文 + Object.values()

⚠️ for-in文はhasOwnPropertyのチェックが必要。

『サバイバルTypeScript』より

この内容をツイートする

関連情報

📄️ 配列をループする方法

JavaScript/TypeScriptで配列をループするには、主にfor文、for-of文、配列のメソッドの3つの方法があります。
  • 質問する ─ 読んでも分からなかったこと、TypeScriptで分からないこと、お気軽にGitHubまで🙂
  • 問題を報告する ─ 文章やサンプルコードなどの誤植はお知らせください。