HTML: Markup language
CSS: Styling language
JavaScript: Scripting language
Web APIs: Programming interfaces
All web technology
Learn web development
Discover our tools
Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
View in English Always switch to English
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年7月.
for...in 文は、オブジェクトの列挙可能プロパティすべてに対して、継承された列挙可能プロパティも含めて反復処理を行います(Symbol がキーになったものは無視します)。
for...in
const object = { a: 1, b: 2, c: 3 }; for (const property in object) { console.log(`${property}: ${object[property]}`); } // 予想される結果: // "a: 1" // "b: 2" // "c: 3"
for (variable in object) statement
variable
それぞれの反復処理において、文字列でプロパティ名を受け取ります。const、let、var の何れかの宣言、または代入ターゲット(例えば、以前宣言された変数や、オブジェクトプロパティ、構造分解パターン)です。var で宣言された変数はループのローカル変数にはなりません。すなわち for...in ループと同じスコープになります。
const
let
var
object
シンボルではない列挙可能なプロパティを反復処理するオブジェクトです。
statement
それぞれの反復処理で実行される文です。 variable を参照することができます。ブロック文を使用して、複数の文を使用することができます。
このループは、オブジェクト自身と、オブジェクトがそのプロトタイプチェーンから継承するプロパティ(プロトタイプチェーンにおいて、オブジェクトから遠いプロトタイプのプロパティよりも、近いプロトタイプのプロパティが優先される)のすべての列挙可能なプロパティを反復処理することになります。
他のループ文と同様に、フロー制御文を statement 内部で使用することができます。
break
continue
for...in ループは、列挙可能なシンボル以外のプロパティに対してのみ反復処理を行います。 Array や Object のような組み込みコンストラクターから生成したオブジェクトは、列挙可能でないプロパティを Array.prototype や Objet.prototype から、例えば Array の indexOf() メソッドや Object の toString() メソッドを継承していますが、これらは for...in ループでは処理されません。
Array
Object
Array.prototype
Objet.prototype
indexOf()
toString()
現代の ECMAScript の仕様では、走査順序は明確に定義されており、 実装同士の間で一貫しています。プロトタイプチェーンのそれぞれの成分内では、非負の整数値(配列の添字となるもの)はすべて値の昇順で最初に走査され、次に文字列のキーがプロパティの作成時系列で昇順に走査されます。
for...in の variable 部分は、= 演算子の前に来ることができるものであれば、何でも受け入れることができます。ループ本体の中で再代入されない限り、const を使用して変数を宣言できます(これらは反復処理毎に別々の変数と見なされるため、変化が可能です)。そうでない場合は、let を使用してください。複数のローカル変数に代入するには構造分解が使用できます。または、for (x.y in iterable) のようなプロパティアクセサーを使用してオブジェクトのプロパティに値を代入することもできます。ただし、using および await using は許可されません。これらの宣言では破棄可能なオブジェクトが必要ですが、変数は常に文字列またはシンボルとなるためです。
=
for (x.y in iterable)
using
await using
古い構文では、初期化子付きのループ変数を var 宣言で行うことができます。これは厳格モードでは構文エラーが発生し、非厳格モードでは無視されます。
for...in はプロパティキーを以下の方法で巡回します。
Object.getOwnPropertyNames()
すなわち、次のようになります。
一般的に、反復処理中は現在アクセスしているプロパティ以外のプロパティを追加、変更、削除しないことが最善です。仕様書では、以下のいずれかの場合に実装が上記のアルゴリズムに従わないことを明示的に許可しています。
これらの場合、実装が期待する動作とは異なる挙動を示す可能性があり、あるいは実装間で異なる挙動を示すことがあります。
配列の添字は整数名を持つ単なる列挙可能なプロパティであり、それ以外は一般的なオブジェクトのプロパティと同じです。for...in ループは、すべての整数キーを他のキーの前に、厳密に増加する順序で反復処理するので、for...in の動作は通常の配列の反復処理に近いものです。しかし、for...in ループは、非整数の名前を持つプロパティや継承されるプロパティも含めて、列挙可能なすべてのプロパティを返します。for...of とは異なり、for...in は配列のイテレーターの代わりにプロパティの列挙を使用します。疎配列では、for...of は空のスロットにアクセスしますが、for...in はそうではありません。
for...of
数値の添字を使った for ループ(か Array.prototype.forEach() か for...of ループ)を使った方が、文字列ではなく数値の添字を返し、インデックス以外のプロパティを避けることができるので適しています。
for
Array.prototype.forEach()
オブジェクトのプロトタイプではなく、オブジェクト自体に付属するプロパティのみを考えたい場合は、以下のテクニックを使用することができます。
Object.keys()
Object.keys は列挙可能な自分自身の文字列プロパティのリストを返す一方、 Object.getOwnPropertyNames は列挙可能でないプロパティも格納します。
Object.keys
Object.getOwnPropertyNames
多くの JavaScript スタイルガイドやリンターは、for...in の使用を推奨していません。なぜなら、プロトタイプチェーン全体を反復処理するので、望んだ結果になることはほとんどなく、より広く使用されている for...of ループと混同してしまう可能性があるからです。for...in の最も実用的な用途はデバッグで、(コンソールに出力するなどして)オブジェクトのプロパティを調べるのに簡単な方法でしょう。オブジェクトがアドホックなキーと値のペアとして使用されるような状況では、for...inによって、それらのキーのいずれかが具体的な値を保持しているかどうかを調べることができます。
以下の for...in ループは、オブジェクトの列挙可能なシンボルではないプロパティをすべて反復し、そのプロパティ名と値を文字列で記録します。
const obj = { a: 1, b: 2, c: 3 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // ログ: // "obj.a = 1" // "obj.b = 2" // "obj.c = 3"
次の関数では Object.hasOwn() の使い方を例示しています。継承されたプロパティは表示されません。
Object.hasOwn()
const triangle = { a: 1, b: 2, c: 3 }; function ColoredTriangle() { this.color = "red"; } ColoredTriangle.prototype = triangle; const obj = new ColoredTriangle(); for (const prop in obj) { if (Object.hasOwn(obj, prop)) { console.log(`obj.${prop} = ${obj[prop]}`); } } // ログ: // "obj.color = red"
警告: このようなコードを自分で書くべきではありません。これは、for...in の動作を特定の特殊なケースで示すためにここに記載しているだけです。
反復処理中に現在のオブジェクトに追加されたプロパティは決して訪問されません。
const obj = { a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); obj.c = 3; } // ログ: // obj.a = 1 // obj.b = 2
シャドウ化されたプロパティは、一度だけ処理されます。
const proto = { a: 1 }; const obj = { __proto__: proto, a: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // ログ: // obj.a = 2 Object.defineProperty(obj, "a", { enumerable: false }); for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); } // 何もログに記録しない。最初に処理された "a" プロパティが列挙不可能であるため。
さらに、以下のケースでは動作が未定義であり、実装が指定されたアルゴリズムから逸脱する傾向があることに留意してください。
反復中にプロトタイプを変更します。
const obj = { a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); Object.setPrototypeOf(obj, { c: 3 }); }
反復処理中のプロパティを削除します。
const obj = { a: 1, b: 2, c: 3 }; // 処理前にプロパティを削除 for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); delete obj.c; } const obj2 = { a: 1, b: 2, c: 3 }; // 処理後にプロパティを削除 for (const prop in obj2) { console.log(`obj2.${prop} = ${obj2[prop]}`); delete obj2.a; }
反復処理中にプロトタイプに追加された列挙可能なプロパティです。
const proto = {}; const obj = { __proto__: proto, a: 1, b: 2 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); proto.c = 3; }
反復処理中にプロパティの列挙可能性を変更します。
const obj = { a: 1, b: 2, c: 3 }; for (const prop in obj) { console.log(`obj.${prop} = ${obj[prop]}`); Object.defineProperty(obj, "c", { enumerable: false }); }
Enable JavaScript to view this browser compatibility table.