for...in 遍历会沿着原型链向上查找,收集所有可枚举的自有属性以及从原型对象继承的可枚举属性。要控制遍历范围,需使用 hasownproperty() 过滤掉继承属性,或改用 object.keys() 仅获取自有属性。

如何区分自有属性与继承属性
在遍历时,for...in 不会停止于当前对象,而是继续访问原型链上的属性。通过检查 obj.hasOwnProperty(key) 可以判断该属性是否直接存在于对象上。如果为 false,则说明该属性来自原型链。

function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log('Hello');
};
const p = new Person('Alice');
for (let key in p) {
if (p.hasOwnProperty(key)) {
console.log('Own: ' + key);
} else {
console.log('Inherited: ' + key);
}
}
运行结果将打印 name 为自有属性,而 sayHello 为继承属性。
为什么某些内置方法不可见
JavaScript 引擎中的许多内置属性和方法(如 toString、valueOf)默认被标记为不可枚举(enumerable: false)。因此,即使它们位于原型链上,for...in 也不会遍历到它们。这是为了防止污染常规的属性迭代逻辑。

const obj = { a: 1, b: 2 };
for (let key in obj) {
console.log(key); // 只输出 'a' 和 'b'
}
上述代码中,尽管 obj 的原型链上有大量方法,但只有显式定义的 a 和 b 被输出。若需查看所有属性包括不可枚举的,可使用 Object.getOwnPropertyNames() 结合原型链遍历。
基于自定义原型属性的具体影响
当开发者向原型添加自定义属性时,这些属性会被 for...in 遍历到,除非显式设置其 enumerable 为 false。这可能导致意外行为,例如在序列化或复制对象时混入非预期数据。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











