このページではfor...in文の解説をしています。
for...in文と構文が似ている、
通常のfor文、
for...of文、
ArrayオブジェクトのforEachメソッド
については各リンク先ページで解説しているのでそちらを参照してください。
for...in文
注意
for...in文はプロパティへのアクセス順序が任意なので
配列に対しての使用が推奨されていません。
プロパティへのアクセス順序が重要な配列に対しては
通常のfor文、
for...of文、
ArrayオブジェクトのforEachメソッド
の使用を検討してください。
このページでは豊富な例を用いてJavaScript(js)のfor...in文の使い方を学ぶことができます。
for...in文はオブジェクトに対して「文字列であるすべての列挙可能プロパティ(キー)」に対してループ・繰り返し処理を行います。 この列挙可能プロパティには継承されたプロパティも含まれます。
冒頭でも説明したとおり、for...in文は任意の順番でプロパティにアクセスして処理を行うので、順序が重要な配列などに対して使用することは推奨されていません。
// 記述例
for (const プロパティが代入される変数 in オブジェクト) {
// 1回のループ中に行う処理
}
TL;DR
基本
// for...in文はオブジェクトの列挙可能なプロパティに対して繰り返し処理を実行する
const object1 = { a: 'A', b: 'B', c: 'C' };
for (const property in object1) {
console.log(property, object1[property]);
}
==> a A
==> b B
==> c C
// Arrayオブジェクトの場合(インデックス値がプロパティ)
const array1 = ['js', 'javascript'];
for (const property in array1) {
console.log(property, array1[property]);
}
==> 0 js
==> 1 javascript
// シンボル(Symbol)型のプロパティは列挙されません
const object2 = { a: 'A', [Symbol('b')]: 'B' };
console.log(object2);
==> { a: 'A', [Symbol(b)]: 'B' }
for (const property in object2) {
console.log(property, object2[property]);
}
==> a A
追加プロパティがある場合
// 列挙可能なプロパティを追加する(Object)
Object.prototype.fooBarNinja1 = 'FooBarNinja-1';
const object1 = { a: 'A', b: 'B' };
object1.func1 = () => 'func1';
for (const property in object1) {
console.log(property, object1[property]);
}
==> a A
==> b B
==> func1 [Function (anonymous)]
==> fooBarNinja1 FooBarNinja-1
// 全ての列挙可能なプロパティを表示(Array)
Object.prototype.fooBarNinja1 = 'FooBarNinja-1';
Array.prototype.fooBarNinja2 = 'FooBarNinja-2';
const array1 = [100, 200];
array1.target = 'TARGET';
for (const property in array1) {
console.log(property, array1[property]);
}
==> 0 100
==> 1 200
==> target TARGET
==> fooBarNinja2 FooBarNinja-2
==> fooBarNinja1 FooBarNinja-1
// 自身のプロパティのみ列挙する(継承したプロパティは除外)
for (const property in array1) {
if (array1.hasOwnProperty(property)) {
console.log(property, array1[property]);
}
}
==> 0 100
==> 1 200
==> target TARGET
for...of文との違い
// 配列の場合
const array1 = ['js', 'JavaScript'];
array1.fooBarNinja = 'FooBarNinja';
// for...in文
for (const element in array1) {
console.log(element);
}
==> 0
==> 1
==> fooBarNinja
// for...of文
for (const element of array1) {
console.log(element);
}
==> js
==> JavaScript
// 文字列の場合
const string1 = 'ES6';
// for...in文
for (const element in string1) {
console.log(element);
}
==> 0
==> 1
==> 2
// for...of文
for (const element of string1) {
console.log(element);
}
==> E
==> S
==> 6
// オブジェクトの場合
const object1 = { a: 'A', b: 'B' };
// for...in文
for (const element in object1) {
console.log(element);
}
==> a
==> b
// for...of文
for (const element of object1) {
console.log(element);
}
==> TypeError: object1 is not iterable
解説
// 記述例
for (const プロパティが代入される変数 in オブジェクト) {
// 1回のループ中に行う処理
}
基本
for...in文はオブジェクトに属する各列挙可能プロパティに対してループ処理を実行します。
ループ処理が実行されるプロパティ(キー)は文字列のものだけであり、Symbol
型など他の型のプロパティはfor...in文で処理されません。
注意事項として、for...in文を使用したループ処理は、プロパティへのアクセス順序が保証されていないことが挙げられます。 そのため、 配列などの順序が重要な型やオブジェクトに対してはfor...in文の使用は推奨されません。 コード例はあくまで挙動の一例としてください。
// オブジェクトの列挙可能なプロパティに対して繰り返し処理を実行
const object1 = { name: 'Wang', age: 20, nationality: 'USA' };
for (const property in object1) {
console.log(property, object1[property]);
}
==> name Wang
==> age 20
==> nationality USA
// Arrayオブジェクト(インデックスがプロパティ)
const array1 = [100, 200, 300];
for (const property in array1) {
console.log(property, array1[property]);
}
==> 0 100
==> 1 200
==> 2 300
// シンボル(Symbol)型のプロパティは列挙されない
const objectWithSymbol2 = { name: 'Wang', [Symbol('age')]: 30, nationality: 'USA' };
console.log(objectWithSymbol2);
==> { name: 'Wang', nationality: 'USA', [Symbol(age)]: 30 }
for (const property in objectWithSymbol2) {
console.log(property, objectWithSymbol2[property]);
}
==> name Wang
==> nationality USA
追加プロパティがある場合
for...in文は列挙することが可能なプロパティに対して処理を行います。 ここでは継承したプロパティや、後から追加したプロパティがどのように扱われるかの例を挙げます。
コード例では継承したプロパティや、後から追加したプロパティもfor...in文の処理の対象となっていることがわかります。
対象オブジェクト自体のプロパティのみに対して処理を行いたい、継承したプロパティなどに対して処理を行いたくない場合は、
hasOwnProperty
メソッドなどを利用してループ処理内で場合分けを実行してください。
// 列挙可能なプロパティを追加(Object)
Object.prototype.fooBarNinja1 = 'FooBarNinja-1';
const object1 = { name: 'Weng' };
object1.func1 = () => 'func1';
for (const property in object1) {
console.log(property, object1[property]);
}
==> name Weng
==> func1 [Function (anonymous)]
==> fooBarNinja1 FooBarNinja-1
// 全ての列挙可能なプロパティを表示(Array)
Object.prototype.fooBarNinja1 = 'FooBarNinja-1';
Array.prototype.fooBarNinja2 = 'FooBarNinja-2';
const array1 = ['js', 'javascript'];
array1.target = 'TARGET';
for (const property in array1) {
console.log(property, array1[property]);
}
==> 0 js
==> 1 javascript
==> target TARGET
==> fooBarNinja2 FooBarNinja-2
==> fooBarNinja1 FooBarNinja-1
// 自身のプロパティのみ列挙(継承したプロパティは除外)
for (const property in array1) {
if (array1.hasOwnProperty(property)) {
console.log(property, array1[property]);
}
}
==> 0 js
==> 1 javascript
==> target TARGET
for...of文との違い
for...in文と構文がよく似ている
for...of文
があります。
以下が主な違いであるので、特徴を意識して使い分けてください。
for...in文
「オブジェクト」の「列挙可能な文字列型のプロパティ」に対して「任意の順序」で処理を実行する。
for...of文
「反復可能なオブジェクト」の「プロパティの値」に対して「定義された順序」で処理を実行する。
// 文字列の場合
const string1 = 'js';
// for...in文
for (const element in string1) {
console.log(element);
}
==> 0
==> 1
// for...of文
for (const element of string1) {
console.log(element);
}
==> j
==> s
// 配列の場合
const array1 = [100, 200];
array1.fooBarNinja = 'FooBarNinja';
// for...in文
for (const element in array1) {
console.log(element);
}
==> 0
==> 1
==> fooBarNinja
// for...of文
for (const element of array1) {
console.log(element);
}
==> 100
==> 200
// オブジェクトの場合
const object1 = { a: 'A', b: 'B' };
// for...in文
for (const element in object1) {
console.log(element);
}
==> a
==> b
// for...of文
for (const element of object1) {
console.log(element);
}
==> TypeError: object1 is not iterable
1次情報
for...inを使用する理由 - MDN web docs