JavaScript中遍历对象的6种方式总结
作者:D_FW
在日常的前端开发中,我们经常需要处理和操作 JavaScript 对象。无论是从接口获取的数据解析,还是状态管理中的数据重组,遍历对象都是一个高频且基础的操作。
然而,很多人只知道 for...in,却忽略了其他更现代、更高效的遍历方式。本文将系统梳理 JavaScript 中遍历对象的 6 种方法,并结合实际场景告诉你:什么时候该用哪种方式?它们的区别是什么?如何避免常见坑?
一、为什么遍历对象这么重要?
对象是 JavaScript 的核心数据类型之一。在 Vue、React、Redux、Axios 等框架和库中,对象无处不在:
- 接口返回的 JSON 数据
 - 表单字段映射
 - 配置项动态处理
 - 国际化语言包
 - 缓存键值存储
 
掌握正确的遍历方式,不仅能提升代码可读性,还能避免性能问题和逻辑错误。
二、6 种遍历对象的方法详解
1. for...in 循环 —— 最基础但需谨慎使用
const user = { name: 'Alice', age: 25, city: 'Beijing' };
 
for (let key in user) {
  console.log(key, user[key]);
}优点:
- 兼容性好,支持老浏览器
 - 可以遍历原型链上的可枚举属性(有时是优势)
 
缺点与风险:
- 会遍历到继承的可枚举属性,可能导致意外输出
 - 如果不加 
hasOwnProperty判断,容易出 bug 
安全写法:
for (let key in user) {
  if (user.hasOwnProperty(key)) {
    console.log(key, user[key]);
  }
}适用场景:需要检查原型链属性的特殊情况(极少),否则不推荐作为首选。
2. Object.keys() —— 获取所有自身可枚举键
Object.keys(user).forEach(key => {
  console.log(key, user[key]);
});优点:
- 只返回对象自身的可枚举属性
 - 返回数组,可链式调用 
.map()、.filter()等 - 是现代开发中最常用的遍历方式之一
 
适用场景:你想“像数组一样”操作对象的键,比如筛选、转换等。
3. Object.values() —— 只关心值的时候用它
console.log(Object.values(user));
// ['Alice', 25, 'Beijing']
 
Object.values(user).forEach(value => {
  console.log(value);
});优点:直接获取所有值,无需再通过 obj[key] 提取
适用场景:统计数值总和、批量处理值、导出为数组等。
4. Object.entries() 强烈推荐:获取键值对
这是 ES2017 引入的强大方法,返回 [key, value] 数组。
Object.entries(user).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});高级用法 1:转为 Map
const map = new Map(Object.entries(user));
console.log(map.get('name')); // 'Alice'高级用法 2:过滤并重建对象
const filtered = Object.fromEntries(
  Object.entries(user).filter(([key, value]) => typeof value === 'string')
);
// { name: 'Alice', city: 'Beijing' }适用场景:需要同时处理键和值、对象转换、动态重构等。这是现代 JS 开发的首选方式!
5. Object.getOwnPropertyNames() —— 包含不可枚举属性
有些属性是“隐藏”的,比如通过 Object.defineProperty 定义的不可枚举属性。
const obj = { a: 1 };
Object.defineProperty(obj, 'b', {
  value: 2,
  enumerable: false
});
 
console.log(Object.keys(obj));           // ['a']
console.log(Object.getOwnPropertyNames(obj)); // ['a', 'b']适用场景:深拷贝、元编程、属性复制等需要完整元信息的场景。
6. Reflect.ownKeys() —— 最全的遍历方式
它能拿到:
- 所有字符串键
 - 所有 Symbol 键
 - 可枚举和不可枚举属性
 
const sym = Symbol('id');
const obj = { name: 'Bob' };
obj[sym] = 100;
 
console.log(Reflect.ownKeys(obj)); // ['name', Symbol(id)]适用场景:编写库、框架、深拷贝工具时,确保不遗漏任何属性。
三、对比总结:该怎么选?
| 方法 | 是否包含继承 | 是否包含不可枚举 | 是否包含 Symbol | 返回类型 | 推荐指数 | 
|---|---|---|---|---|---|
for...in | ✅ 是 | ❌ 否 | ❌ 否 | - | ⭐⭐☆ | 
Object.keys() | ❌ 否 | ❌ 否 | ❌ 否 | 字符串数组 | ⭐⭐⭐⭐ | 
Object.values() | ❌ 否 | ❌ 否 | ❌ 否 | 值数组 | ⭐⭐⭐⭐ | 
Object.entries() | ❌ 否 | ❌ 否 | ❌ 否 | [k,v] 数组 | ⭐⭐⭐⭐⭐ | 
getOwnPropertyNames | ❌ 否 | ✅ 是 | ❌ 否 | 字符串数组 | ⭐⭐⭐☆ | 
Reflect.ownKeys() | ❌ 否 | ✅ 是 | ✅ 是 | 所有键数组 | ⭐⭐⭐⭐ | 
结论:90% 的场景推荐使用 Object.entries(),语义清晰、功能强大、兼容现代开发需求。
四、实战技巧 & 常见误区
误区 1:直接 JSON.stringify(Map) 或 JSON.stringify(Symbol)
const obj = { [Symbol('x')]: 1 };
console.log(JSON.stringify(obj)); // {} —— Symbol 被忽略!解决方案:使用 Reflect.ownKeys() 处理 Symbol。
误区 2:认为 for...in 和 Object.keys() 一样
function Person() {}
Person.prototype.say = function() {};
 
const p = new Person();
p.name = 'Tom';
 
console.log(Object.keys(p)); // ['name']
for (let k in p) console.log(k); // name, say(包括原型方法!)建议:除非特殊需求,优先使用 Object.keys() 或 entries()。
技巧:快速转换对象结构
// 将 { id1: '张三', id2: '李四' } 转为数组
const users = Object.entries(obj).map(([id, name]) => ({ id, name }));五、结语
遍历对象看似简单,实则暗藏玄机。选择合适的遍历方式,不仅能让你的代码更健壮,还能提升开发效率和可维护性。
记住一句话:“能用 Object.entries() 的地方,就不要用 for...in。”
随着 ES6+ 的普及,Object.keys/values/entries 已成为现代 JavaScript 的标准实践。掌握它们,是你迈向高级前端开发者的重要一步。
以上就是JavaScript中遍历对象的6种方式总结的详细内容,更多关于JavaScript遍历对象的资料请关注脚本之家其它相关文章!
