for..in
根据ES6遍历所有可枚举的String
属性,它是否需要访问同一属性,因为它的后代中的非可枚举属性会覆盖它(相同的属性字符串) ?如下所示Object.prototype.indexOf
不会遍历代码Array
。上面链接中的pseduo代码只暗示重复的可枚举属性不会再次枚举,似乎不包括这种情况。
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);
}
答案 0 :(得分:2)
不,不枚举不可枚举的属性名称。无论它们是否影响可枚举的继承属性。
您的测试和链接的规范文本都证实了这一点:
[...]如果原型的属性与已经处理的属性同名,则不处理该原型的属性[...]
答案 1 :(得分: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;
}
}