2016-12-08 5 views
2

for..inES6によると、すべての列挙型のStringが通過しますが、同じプロパティを参照する必要がありますか?その列挙型以外のプロパティで上書きされますか?以下のコードのようにArrayの場合、Object.prototype.indexOfはトラバースされません。上のリンクのpseduoコードは、重複した列挙可能なプロパティが再び列挙されないことを暗示しているだけで、このケースをカバーしていないようです。for..in traverseプロパティは、プロトタイプチェーンの列挙できないプロパティによって上書きされますか?

Object.prototype.indexOf = "test"; 
 
var arr = []; 
 
for (var item in arr) { 
 
    // Object.prototype.indexOf is overwritten for arr by Array.prototype.indexOf, 
 
    // the latter is non-enumerable 
 
    console.log(item); 
 
}

+1

偽のコードがこのケースをカバーしていないと思われる理由はわかりません。私には明らかです。 – Bergi

+0

@Bergiあなたは正しいです、私は疑似コードの再帰部分を見逃しました。 – Thomson

答えて

1

for...inループはEnumerateObjectProperties反復子によって指定されたプロパティを反復します。ターゲット・オブジェクトのプロパティを列挙

は再帰的に、そうで そのプロトタイプの性質、およびプロトタイプのプロトタイプ、および を列挙することを含みます。反復子のnextメソッドによってすでに処理されているプロパティと同じ名前の場合は、プロトタイプのプロパティは処理されません。このプロパティは、 のメソッドと同じ名前です。プロトタイプ オブジェクトのプロパティがすでに処理されているかどうかを判断するときは、[[Enumerable]]属性 の値は考慮されません。

したがって、オブジェクトに列挙できないプロパティがある場合、処理されますが反復されません。さらにプロトタイプチェーン内に同じプロパティがありますが、現在は列挙可能な場合は、処理されたと見なされ、したがって反復されません。

提案された実装コードでは、列挙できないために生成されない場合でも、キーは常に訪問済みセットに追加されることがわかります。

function* EnumerateObjectProperties(obj) { 
    let visited = new Set; 
    for (let key of Reflect.ownKeys(obj)) { 
    if (typeof key === "string") { 
     let desc = Reflect.getOwnPropertyDescriptor(obj, key); 
     if (desc && !visited.has(key)) { 
     visited.add(key); // <-- Added even if not enumerable 
     if (desc.enumerable) yield key; 
     } 
    } 
    } 
    let proto = Reflect.getPrototypeOf(obj) 
    if (proto === null) return; 
    for (let protoName of EnumerateObjectProperties(proto)) { 
    if (!visited.has(protoName)) yield protoName; 
    } 
} 
2

いいえ、列挙できないプロパティ名は列挙されません。列挙可能なプロパティを列挙できるかどうかにかかわらず

テストおよびリンク仕様のテキストの両方がこの確認:それはすでに処理されたプロパティと同じ名前を持つ場合、プロトタイプのプロパティが処理されない[...]

を[...]

関連する問題