for...in循环遍历对象自身及原型链上所有可枚举属性(不含不可枚举属性和symbol键),需用hasownproperty()区分自有与继承属性,常见陷阱是误触原型污染,推荐用object.keys()或手动遍历加筛选确保安全。

for...in 循环会遍历对象自身及其原型链上所有**可枚举(enumerable: true)的自有属性和继承属性**,但不包括不可枚举属性(如 constructor、toString 等原生方法)以及 Symbol 属性。
for...in 遍历的范围
它沿原型链向上查找,直到 Object.prototype 为止。只要某个属性是可枚举的,并且存在于当前对象或其任意原型上,就会被遍历到。
- 包括对象自身的可枚举属性
- 包括从 prototype 继承来的可枚举属性(比如通过
Object.prototype.method = function(){}添加的) - 不包括不可枚举属性(如
Object.defineProperty(obj, 'x', { enumerable: false })定义的) - 不包括 Symbol 类型的键
如何区分“自有属性”和“继承属性”
仅靠 for...in 无法自动区分;需配合 hasOwnProperty() 判断:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log('自有属性:', key);
} else {
console.log('继承属性:', key);
}
}
常见陷阱与规避建议
直接用 for...in 遍历对象容易误触原型上的扩展属性(尤其在全局污染或第三方库修改了原型时)。
- 避免给 Object.prototype 添加可枚举属性(推荐用
Object.defineProperty并设enumerable: false) - 需要只遍历自有属性时,优先使用
Object.keys()+forEach或for...of - 需要遍历所有可枚举属性(含继承)且确保安全,可用
Object.getOwnPropertyNames()结合getPrototypeOf手动遍历原型链,再筛选enumerable: true
一个简单示例
假设:
function Animal() {}
Animal.prototype.eat = function() {};
Object.defineProperty(Animal.prototype, 'species', {
value: 'mammal',
enumerable: false // 不会被 for...in 遍历
});
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {};
const dog = new Dog();
dog.name = 'Leo'; // 自有可枚举属性
for (let key in dog) {
console.log(key); // 输出: 'name', 'eat', 'bark'
}
这里 name 是自有属性,eat 和 bark 分别来自 Animal.prototype 和 Dog.prototype,都是可枚举的,所以都被遍历到了;而 species 因 enumerable: false 被跳过。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










