【JavaScript】对象遍历方法汇总

张开发
2026/4/15 7:52:11 15 分钟阅读

分享文章

【JavaScript】对象遍历方法汇总
for...in循环for...in主要用于遍历对象的属性通常是遍历对象的可枚举字符串属性包括继承的属性。- 可枚举属性看属性是否 enumerable 。它遍历对象的属性名称键名对于数组来说就是索引而不是属性的值。遍历对象属性时包括自身的属性和原型链上的属性。想要获取自身的属性需要加一个判断 Object.prototype.hasOwnProperty.call(obj, key) 。示例constperson{name:John,age:30,job:Engineer};for(letkeyinperson){console.log(key: person[key]);}输出name: John age: 30 job: Engineerfor...of循环for...of用于遍历可迭代对象如数组、字符串、Map、Set 等并访问它们的值。- 对象是否可迭代看对象是否实现了 Symbol.iterator 方法。它不会遍历普通对象的属性只会遍历数据集合中的元素。与传统的 for 循环和 forEach 方法不同for…of 循环不需要使用索引来访问 元素而是直接返回元素的值。这使得代码更简洁、易读。示例constcolors[red,green,blue];for(letcolorofcolors){console.log(color);}输出red green bluefor...in和for...of的底层实现区别以下都使用 js 模拟底层 c 实现。for…in遍历对象的可枚举属性名key。对数组来说它会遍历索引作为字符串。底层机制for...in遍历时会去对象原型链上查找可枚举属性。顺序先自身属性再原型链。本质上就是调用Object.keys(obj) 原型链查找的一种语法糖。 示例letobj{a:1,b:2};for(letkeyinobj){console.log(key);// a, b}等价于Object.keys(obj).forEach(keyconsole.log(key));⚠️ 注意只遍历可枚举属性enumerable: true。顺序不是严格定义的尤其对象属性顺序但现代浏览器通常会先数字属性升序再字符串属性插入顺序。这里注意思考普通对象和Map 的属性顺序区别。关键记忆方法枚举就是像列举物品一样列出来(for…in / Object.keys)那么怎么知道列出的是谁呢这时就需要用到 key 保证物品的唯一性和准确性所以关注点在于 key。for...of遍历可迭代对象iterable的值。包括数组、字符串、Map、Set、arguments、NodeList、自定义实现[Symbol.iterator]的对象。// Object 无法直接迭代因此我们手动实现 [Symbol.iterator] 方法constobj{a:1,b:2,c:3,[Symbol.iterator](){constvaluesObject.values(this);letindex0;return{next(){// next 方法返回 value 和 doneif(indexvalues.length){return{value:values[index],done:false};}return{value:undefined,done:true};}};}};// ✅ 可迭代for(constvalofobj){console.log(val);}// 1 2 3底层机制本质上是基于迭代器协议Iterator Protocol实现的。迭代器协议要求对象实现obj[Symbol.iterator]方法返回一个迭代器对象。迭代器对象有一个next()方法每次调用返回{value:any,done:boolean}for...of会循环调用next()直到done: true。关键记忆方法迭代讲究一个逐个取出的逻辑所以重点在是否能够取出所以关注点在于具体的值。示例letarr[10,20,30];for(letvalofarr){console.log(val);// 10, 20, 30}等价于letitarr[Symbol.iterator]();letres;while(!(resit.next()).done){console.log(res.value);}源码角度JS 引擎实现如果你真的去看 V8 / SpiderMonkey 的源码大概流程是for...in调用内部抽象操作EnumerateObjectProperties收集对象及原型链上的可枚举属性 key。for...of调用GetIterator(obj)即获取obj[Symbol.iterator]()然后反复调用IteratorNext()。也就是说for...in 遍历属性键基于对象自身 原型链。for...of 遍历迭代器的值基于[Symbol.iterator]协议。forEach用于遍历数组的元素对每个元素执行一个回调函数。提供了更高级别的抽象让你可以更容易地执行数组操作如映射、筛选、累加等。不适用于普通对象只适用于数组。示例javascript Copy code const numbers [1, 2, 3, 4, 5]; numbers.forEach(function(number) { console.log(number); }); forEach 和 map特性forEachmap返回值undefined新数组用途遍历数组执行副作用操作遍历数组生成新的数组常见使用场景处理 DOM、修改外部变量等转换数组中的每个元素是否改变原数组否否性能比map略快因为不返回数组创建新数组有额外开销主要区别总结for…in 用于遍历对象的属性for…of 用于遍历可迭代对象的元素而 forEach 用于遍历数组元素。for…in 适用于对象for…of 和 forEach 适用于数组。forEach 允许你传递一个回调函数更容易进行复杂的操作而 for…in 和 for…of 较为基础只能用于遍历。注意遍历对象时for…in 会遍历继承的属性这可能需要额外的处理。Object.keys()只返回对象自身的可枚举字符串属性列表。Object.values(obj) 直接遍历值Object.entries(obj) 配合解构 [key, value]Object.getOwnPropertyNames()返回对象自身的全部字符串属性含不可枚举属性。Object.getOwnPropertySymbols()返回对象自身的全部 Symbol 属性。Reflect.ownKeys()返回对象自身的所有属性。Reflect.ownKeys() Object.getOwnPropertyNames() Object.getOwnPropertySymbols() 。以上几种对象方法的遍历顺序字符串键整数索引升序- 其他字符串插入顺序Reflect.ownKeys所有字符串键 - 所有 Symbol 键性能考量Object.keys通常比for…in hasOwnProperty更快。Reflect.ownKeys开销可能略高但结果最全面。

更多文章