for..in循环
for…in 循环
for..in
循环也会迭代继承的属性。
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
// Object.keys 只返回自己的 key
alert(Object.keys(rabbit)); // jumps
// for..in 会遍历自己以及继承的键
for(let prop in rabbit) alert(prop); // jumps,然后是 eats
// --------------------------------------------------分割线
// 如果这不是我们想要的,并且我们想排除继承的属性,那么这儿有一个内建方法 obj.hasOwnProperty(key):如果 obj 具有自己的(非继承的)名为 key 的属性,则返回 true。
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
for(let prop in rabbit) {
let isOwn = rabbit.hasOwnProperty(prop);
if (isOwn) {
alert(`Our: ${prop}`); // Our: jumps
} else {
alert(`Inherited: ${prop}`); // Inherited: eats
}
}
-
注意,这有一件很有趣的事儿。方法
rabbit.hasOwnProperty
来自哪儿?我们并没有定义它。从上图中的原型链我们可以看到,该方法是Object.prototype.hasOwnProperty
提供的。换句话说,它是继承的。 -
如果
for..in
循环会列出继承的属性,那为什么hasOwnProperty
没有像eats
和jumps
那样出现在for..in
循环中? -
答案很简单:它是不可枚举的。就像
Object.prototype
的其他属性,hasOwnProperty
有enumerable:false
标志。并且 for..in 只会列出可枚举的属性。这就是为什么它和其余的Object.prototype
属性都未被列出。 -
几乎所有其他键/值获取方法都忽略继承的属性,几乎所有其他键/值获取方法,例如
Object.keys
和Object.values
等。都会忽略继承的属性。它们只会对对象自身进行操作。不考虑 继承自原型的属性。