JavaScript 遍历对象的五种核心方式详解
本文详细解析JavaScript中遍历对象的五种主要方式,包括for...in、Object.keys、Object.getOwnPropertyNames、Object.getOwnPropertySymbols以及Reflect.ownKeys。通过对比它们对可枚举、不可枚举及Symbol类型属性的处理差异,帮助开发者根据实际需求选择最合适的遍历方法,并附带Object.values、Object.entries及hasOwnProperty等扩展用法的说明。
准备
首先构建一个用于测试的对象实例obj。
代码清单1
var notEnum = Symbol("继承不可枚举symbol");
var proto = {
[Symbol("继承可枚举symbol")]: "继承可枚举symbol",
name: "继承可枚举属性"
};
// 不可枚举属性
Object.defineProperty(proto, "age", {
value: "继承不可枚举属性"
});
// 不可枚举symbol属性
Object.defineProperty(proto, notEnum, {
value: "继承不可枚举symbol"
});
var obj = {
job1: "自有可枚举属性1",
job2: "自有可枚举属性2",
[Symbol("自有可枚举symbol")]: "自有可枚举symbol"
};
// 继承
Object.setPrototypeOf(obj, proto);
// 不可枚举属性
Object.defineProperty(obj, "address", {
value: "自有不可枚举属性"
});
// 不可枚举symbol属性
var ownNotEnum = Symbol("自有不可枚举symbol");
Object.defineProperty(obj, ownNotEnum, {
value: "自有不可枚举symbol"
});
五种武器
for…in
这是对象遍历领域中最经典的方法。通过该方式可以遍历对象自身以及其原型链上所有可枚举的属性,但不会包含Symbol类型的属性。
代码清单2
for(var attr in obj){
console.log(attr,"==",obj[attr]);
}
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
name == 继承可枚举属性
*/
Object.keys
该方法返回一个数组,包含对象自身所有可枚举属性的键名,同样不包含Symbol类型的属性。
代码清单3
Object.keys(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
*/
Object.getOwnPropertyNames
此方法返回一个数组,包含对象自身所有非Symbol类型的属性名称,无论这些属性是否可枚举。
代码清单4
Object.getOwnPropertyNames(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
address == 自有不可枚举属性
*/
Object.getOwnPropertySymbols
该方法返回一个数组,包含对象自身所有Symbol类型的属性名称,无论其是否可枚举。
代码清单5
Object.getOwnPropertySymbols(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
Symbol(自有可枚举symbol) == 自有可枚举symbol
Symbol(自有不可枚举symbol) == 自有不可枚举symbol
*/
Reflect.ownKeys
这是功能最全面的API,返回一个数组,包含对象自身所有的属性名称,既包括不可枚举的属性,也涵盖Symbol类型的属性。
代码清单6
Reflect.ownKeys(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
address == 自有不可枚举属性
Symbol(自有可枚举symbol) '==' '自有可枚举symbol'
Symbol(自有不可枚举symbol) '==' '自有不可枚举symbol'
*/
总结
如同武器库的使用手册,开发者应根据具体场景选择最合适的遍历工具。
| api | 操作 | 自身属性 | 不可枚举属性 | 继承属性 | Symbol属性 |
|---|---|---|---|---|---|
| for…in | 遍历 | yes | no | yes | no |
| Object.keys | 返回属性数组 | yes | no | no | no |
| Object.getOwnPropertyNames | 返回非Symbol属性数组 | yes | yes | no | no |
| Object.getOwnPropertySymbols | 返回Symbol属性数组 | yes | yes | no | yes |
| Reflect.ownKeys | 返回属性数组 | yes | yes | no | yes |
在五种方法中,Reflect.ownKeys最为强大,它能同时处理Symbol和不可枚举属性,效果相当于Object.getOwnPropertyNames与Object.getOwnPropertySymbols的结合体。
扩展
Object.values
该方法返回一个数组,包含对象自身所有可枚举属性的值,不包含Symbol类型的属性。
代码清单7
Object.values(obj).map((val)=>{
console.log(val);
});
/*
自有可枚举属性1
自有可枚举属性2
*/
Object.entries
此方法返回一个二维数组,包含对象自身所有可枚举属性的键值对,同样不包含Symbol类型的属性。
代码清单7
Object.entries(obj).map((val)=>{
console.log(val);
});
/*
[ 'job1', '自有可枚举属性1' ]
[ 'job2', '自有可枚举属性2' ]
*/
hasOwnProperty
用于检测对象自身是否包含指定的属性,返回布尔值。
注意:MDN指出JavaScript并未保护hasOwnProperty属性名,因此对象可能覆盖该属性。建议始终使用原型链上的Object.prototype.hasOwnProperty.call(obj, attr)来确保正确性。
代码清单8
for(var attr in obj){
if(Object.prototype.hasOwnProperty.call(obj,attr)){
console.log("自有属性::",attr);
}else{
console.log("继承属性::",attr);
}
}
/*
自有属性:: job1
自有属性:: job2
继承属性:: name
*/
propertyIsEnumerable
用于检测指定属性在对象中是否可枚举,返回布尔值。
代码清单9
Reflect.ownKeys(obj).map((attr) => {
if (Object.prototype.propertyIsEnumerable.call(obj, attr)) {
console.log("可枚举属性::", attr);
} else {
console.log("不可枚举属性::", attr);
}
});
/*
可枚举属性:: job1
可枚举属性:: job2
不可枚举属性:: address
可枚举属性:: Symbol(自有可枚举symbol)
不可枚举属性:: Symbol(自有不可枚举symbol)
*/
参考
MDN Object
总结
至此,关于JavaScript遍历对象的五种方式介绍完毕。如需了解更多相关内容,请查阅本站往期文章或继续浏览后续文章,感谢支持!
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
