オブジェクトがデフォルトで反復できないのはなぜですか?
オブジェクトの反復に関連する質問が常にあります。一般的な解決策は、オブジェクトのプロパティを反復し、その方法でオブジェクト内の値にアクセスすることです。これは非常に一般的であるため、オブジェクト自体が反復可能ではないのはなぜか疑問に思います。
ES6のようなステートメントは、for...of
デフォルトでオブジェクトに使用すると便利です。これらの機能は、{}
オブジェクトを含まない特別な「反復可能なオブジェクト」でのみ使用できるため、使用するオブジェクトに対してこれを機能させるには、フープを実行する必要があります。
for ... ofステートメントは、反復可能なオブジェクト (Array、Map、Set、argumentsオブジェクトなどを含む)を反復処理するループを作成します。
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for (let [key, value] of entries(example)) {
console.log(key);
console.log(value);
for (let [key, value] of entries(value)) {
console.log(key);
console.log(value);
}
}
上記は、Firefox(ES6をサポート)でコードを実行したときに期待する順序でデータを適切にログに記録します。
デフォルトでは、{}
オブジェクトは反復可能ではありませんが、なぜですか?不利な点は、オブジェクトが反復可能であることの潜在的な利点を上回りますか?これに関連する問題は何ですか?
ために加えて、{}
オブジェクトは「アレイ状」コレクションとは異なっているような「反復可能オブジェクト」NodeList
、HtmlCollection
およびarguments
、それらが配列に変換することができません。
例えば:
var argumentsArray = Array.prototype.slice.call(arguments);
または配列メソッドで使用します:
Array.prototype.forEach.call(nodeList, function (element) {})
。
上記の質問に加えて、{}
オブジェクトを反復可能にする方法についての実用的な例を見てみたいと思います[Symbol.iterator]
。特に、に言及した人からです。これにより、これらの新しい{}
「反復可能オブジェクト」がのようなステートメントを使用できるようになりfor...of
ます。また、オブジェクトを反復可能にすると、オブジェクトを配列に変換できるのではないかと思います。
以下のコードを試しましたが、が表示されTypeError: can't convert undefined to object
ます。
var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
// I want to be able to use "for...of" for the "example" object.
// I also want to be able to convert the "example" object into an Array.
example[Symbol.iterator] = function* (obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
};
for (let [key, value] of example) { console.log(value); } // error
console.log([...example]); // error
Symbol.iterator
プロパティが反復可能です。したがって、そのプロパティを実装する必要があります。オブジェクトが反復可能でない理由の1つの考えられる説明は、すべてがオブジェクトであるため(もちろんプリミティブを除く)、これはすべてが反復可能であることを意味する可能性があります。ただし、関数または正規表現オブジェクトを反復処理するとはどういう意味ですか?