news 2026/6/15 13:58:10

js遍历数组和对象的常用方法有哪些?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
js遍历数组和对象的常用方法有哪些?

精通 JS 遍历:数组与对象的高效遍历方法论(2026 版)

遍历是 JavaScript 数据处理的基石,从前端 DOM 渲染到后端数据聚合,几乎所有业务场景都离不开数组和对象的遍历操作。但新手常陷入 “方法用错、性能低效、边界踩坑” 的困境 —— 比如用for...in遍历数组、用forEach强行终止循环、忽略reduce初始值导致异常。本文将从场景适配性能优化避坑指南三个维度,系统拆解数组与对象的遍历方法,结合实战案例和最佳实践,帮你实现 “选对方法、写对代码、用对性能” 的目标。

一、数组遍历:按场景选方法,而非 “一招鲜”

数组遍历的核心是 “匹配业务意图”:是单纯遍历?是生成新数组?是筛选数据?还是聚合计算?不同意图对应不同最优方法,以下按 “基础可控型”“函数式迭代型”“特殊场景型” 分类讲解。

1. 基础可控型遍历(性能优先)

这类方法完全掌控遍历过程,支持终止 / 跳过,适合大数据量、需精细控制的场景。

(1)原生 for 循环(性能天花板)

最底层、性能最优的遍历方式,无任何额外开销,适合 10 万级以上大数据量遍历。

javascript

运行

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // 基础版 for (let i = 0; i < arr.length; i++) { // 终止循环:找到第一个大于5的数就停止 if (arr[i] > 5) { console.log("找到目标值:", arr[i]); break; } console.log("当前值:", arr[i]); } // 性能优化版(缓存长度,避免每次读取arr.length) for (let i = 0, len = arr.length; i < len; i++) { // 跳过偶数 if (arr[i] % 2 === 0) continue; console.log("奇数:", arr[i]); } // 反向遍历(适合从后删除元素的场景) for (let i = arr.length - 1; i >= 0; i--) { if (arr[i] < 3) arr.splice(i, 1); // 从后删除避免索引错乱 } console.log(arr); // [3,4,5,6,7,8,9,10]

核心优势

  • 性能第一,无函数调用、迭代器等额外开销;
  • 支持break(终止)、continue(跳过)、反向遍历;
  • 可直接操作索引,适合修改原数组的场景。
(2)for...of 循环(ES6+,简洁可控)

ES6 迭代器语法,兼顾简洁性和可控性,支持遍历所有可迭代对象(数组、Set、Map、字符串等)。

javascript

运行

const arr = [1, 2, 3, 4, 5]; // 基础遍历元素 for (const item of arr) { if (item === 3) break; // 支持终止 console.log(item); // 1,2 } // 同时获取索引和元素(结合entries()) for (const [index, item] of arr.entries()) { console.log(`索引${index}:${item}`); } // 遍历Set(可迭代对象示例) const set = new Set([1, 2, 3]); for (const item of set) { console.log(item); }

核心优势

  • 语法简洁,比原生 for 循环易读;
  • 支持break/continue,弥补 forEach 的缺陷;
  • 适配所有可迭代对象,通用性强。

2. 函数式迭代方法(可读性优先)

ES5+ 新增的数组原型方法,基于函数式编程思想,无需手动控制索引,是日常开发的主流选择。所有方法均不修改原数组,核心差异在于 “返回值” 和 “终止逻辑”。

核心方法对比表(建议收藏)
方法名核心用途返回值终止逻辑典型场景
forEach单纯遍历无(undefined)无法终止(return 仅跳过当前轮次)列表渲染、无返回值的遍历操作
map映射转换新数组(长度与原数组一致)无终止(遍历所有元素)数据格式转换(如接口数据适配)
filter筛选数据新数组(符合条件的元素)无终止(遍历所有元素)条件筛选(如筛选已完成的任务)
some存在性判断布尔值(true/false)返回 true 时立即终止判断是否有符合条件的元素
every全量判断布尔值(true/false)返回 false 时立即终止判断所有元素是否符合规则
find查找元素第一个符合条件的元素 /undefined返回 true 时立即终止查找唯一元素(如根据 ID 找用户)
findIndex查找索引第一个符合条件的索引 /-1返回 true 时立即终止查找元素位置(如定位错误数据)
reduce聚合计算最终聚合值无终止(遍历所有元素)求和、拼接、扁平化数组等
实战示例(带业务场景)

javascript

运行

const users = [ { id: 1, name: "张三", age: 22, status: "active" }, { id: 2, name: "李四", age: 18, status: "inactive" }, { id: 3, name: "王五", age: 25, status: "active" }, ]; // 1. forEach:渲染用户列表(无返回值) users.forEach(user => { console.log(`用户${user.name}:状态${user.status}`); }); // 2. map:转换数据格式(前端适配) const userOptions = users.map(user => ({ label: user.name, value: user.id })); console.log(userOptions); // [{label: '张三', value: 1}, {label: '李四', value: 2}, {label: '王五', value: 3}] // 3. filter:筛选活跃用户 const activeUsers = users.filter(user => user.status === "active"); console.log(activeUsers); // 张三、王五 // 4. some:判断是否有未成年用户 const hasMinor = users.some(user => user.age < 18); console.log(hasMinor); // false(李四18岁,不满足<18) // 5. every:判断所有用户是否成年 const allAdult = users.every(user => user.age >= 18); console.log(allAdult); // true // 6. find:根据ID查找用户 const targetUser = users.find(user => user.id === 2); console.log(targetUser); // 李四 // 7. reduce:计算所有用户年龄总和 const totalAge = users.reduce((sum, user) => sum + user.age, 0); console.log(totalAge); // 22+18+25=65 // 8. reduce进阶:按状态分组 const groupedUsers = users.reduce((obj, user) => { if (!obj[user.status]) obj[user.status] = []; obj[user.status].push(user); return obj; }, {}); console.log(groupedUsers); // {active: [张三, 王五], inactive: [李四]}
避坑要点:
  • ❌ 不要用forEach尝试终止循环(return无效),改用some/everyfor...of
  • reduce必须传初始值(第二个参数),否则空数组会报错,单元素数组直接返回该元素;
  • map不要用于无返回值的遍历(浪费性能),改用forEach
  • some/every是 “短路遍历”,找到结果立即终止,比forEach+ 判断更高效。

3. 特殊场景遍历

(1)for...in(不推荐遍历数组)

for...in设计初衷是遍历对象,遍历数组时会包含原型链属性,且索引为字符串类型:

javascript

运行

Array.prototype.foo = "原型属性"; const arr = [1, 2, 3]; for (const key in arr) { console.log(key); // 0,1,2,foo(包含原型属性) console.log(typeof key); // string(索引是字符串) }

结论:数组遍历绝对不要用for...in

(2)Array.from(遍历类数组 / 可迭代对象)

适合将 DOM 集合、arguments 等类数组对象转为数组并遍历:

javascript

运行

// 遍历DOM节点列表 const lis = document.querySelectorAll("li"); const liTexts = Array.from(lis, li => li.textContent); console.log(liTexts); // 所有li的文本内容 // 遍历字符串(可迭代对象) const str = "hello"; const charArr = Array.from(str, char => char.toUpperCase()); console.log(charArr); // ['H','E','L','L','O']

二、对象遍历:精准获取键值对

对象遍历的核心是 “区分自身属性 / 原型属性”“可枚举 / 不可枚举属性”“普通键 / Symbol 键”,以下按 “常用程度” 排序讲解。

1. 主流方案:Object.entries () + for...of(ES6+)

最推荐的对象遍历方式,无需过滤原型属性,直接获取键值对,语法简洁:

javascript

运行

const user = { name: "张三", age: 22, status: "active" }; // 遍历键值对 for (const [key, value] of Object.entries(user)) { console.log(`${key}: ${value}`); } // 结合解构+forEach Object.entries(user).forEach(([key, value]) => { console.log(`${key}: ${value}`); });

核心优势

  • 仅遍历对象自身可枚举属性,无需hasOwnProperty过滤;
  • 直接获取 [key, value],无需手动obj[key]取值;
  • 语法统一,与数组遍历风格一致。

2. 基础方案:for...in + hasOwnProperty

传统对象遍历方法,需手动过滤原型属性,否则会遍历到原型链上的可枚举属性:

javascript

运行

const user = { name: "张三", age: 22 }; Object.prototype.foo = "原型属性"; // 正确用法:过滤原型属性 for (const key in user) { if (user.hasOwnProperty(key)) { console.log(`${key}: ${user[key]}`); // 仅name、age } }

适用场景:仅兼容 ES5 的老旧项目,新项目优先用Object.entries()

3. 专项方案:按需求获取键 / 值

  • Object.keys(obj):获取自身可枚举键的数组;
  • Object.values(obj):获取自身可枚举值的数组;

javascript

运行

const user = { name: "张三", age: 22 }; // 获取所有键 const keys = Object.keys(user); // ['name', 'age'] // 获取所有值 const values = Object.values(user); // ['张三', 22] // 遍历键 keys.forEach(key => console.log(key)); // 遍历值 values.forEach(value => console.log(value));

4. 特殊场景:遍历不可枚举 / Symbol 属性

业务中极少用到,但面试常考,需掌握Object.getOwnPropertyNames()Object.getOwnPropertySymbols()

javascript

运行

// 定义不可枚举属性和Symbol键 const symKey = Symbol("id"); const obj = { name: "张三" }; // 定义不可枚举属性 Object.defineProperty(obj, "id", { value: 1001, enumerable: false // 不可枚举 }); // 定义Symbol键 obj[symKey] = "symbol-value"; // 1. 获取所有自身属性(含不可枚举,不含Symbol) const allKeys = Object.getOwnPropertyNames(obj); console.log(allKeys); // ['name', 'id'] // 2. 获取所有Symbol键 const symKeys = Object.getOwnPropertySymbols(obj); console.log(symKeys); // [Symbol(id)] // 3. 遍历所有自身属性(含不可枚举+Symbol) const allProps = [...allKeys, ...symKeys]; allProps.forEach(key => { console.log(`${key}: ${obj[key]}`); });

三、选型决策树(快速选对方法)

数组遍历选型

预览

查看代码

无返回值

新数组(映射)

新数组(筛选)

布尔值(存在性)

单个元素/索引

聚合值(求和/分组)

数组遍历

是否需要终止/跳过?

for循环 / for...of

是否需要返回值?

forEach

map

filter

some/every

find/findIndex

reduce

graph TD A[数组遍历] --> B{是否需要终止/跳过?} B -->|是| C[for循环 / for...of] B -->|否| D{是否需要返回值?} D -->|无返回值| E[forEach] D -->|新数组(映射)| F[map] D -->|新数组(筛选)| G[filter] D -->|布尔值(存在性)| H[some/every] D -->|单个元素/索引| I[find/findIndex] D -->|聚合值(求和/分组)| J[reduce]

无返回值

新数组(映射)

新数组(筛选)

布尔值(存在性)

单个元素/索引

聚合值(求和/分组)

数组遍历

是否需要终止/跳过?

for循环 / for...of

是否需要返回值?

forEach

map

filter

some/every

find/findIndex

reduce

豆包

你的 AI 助手,助力每日工作学习

对象遍历选型

预览

查看代码

生成失败,请重试

graph TD A[对象遍历] --> B{是否需要键值对?} B -->|是| C[Object.entries() + for...of] B -->|否| D{仅需键?} D -->|是| E[Object.keys()] D -->|否| F[Object.values()] A --> G{是否需遍历不可枚举/Symbol?} G -->|是| H[Object.getOwnPropertyNames() + Object.getOwnPropertySymbols()] G -->|否| I[主流方案]

生成失败,请重试

豆包

你的 AI 助手,助力每日工作学习

四、性能与最佳实践

1. 性能对比(10 万条数据测试)

方法执行时间(ms)适用场景
for 循环~5大数据量、需极致性能
for...of~8中等数据量、需简洁可控
forEach~10小数据量、无终止需求
map/filter~12小数据量、需返回新数组
for...in(数组)~50绝对避免

2. 最佳实践

  • ✅ 业务代码优先保证可读性,大数据量(10 万 +)再优化性能;
  • ✅ 数组遍历优先用map/filter/some/every/reduce(语义化),而非 forEach + 手动逻辑;
  • ✅ 对象遍历优先用Object.entries(),替代for...in
  • ✅ 避免在遍历中修改原数组(如 splice/push),易导致索引错乱;
  • ✅ 遍历嵌套数据时,优先扁平化(如flatMap)后再遍历,减少嵌套层级。

总结

  1. 数组遍历的核心是 “匹配业务意图”:需终止用for/for...of,需映射用map,需筛选用filter,需聚合用reduce
  2. 对象遍历优先选择Object.entries() + for...of,无需手动过滤原型属性,语法简洁;
  3. 选择遍历方法的核心原则:语义化 > 简洁性 > 性能,仅在大数据量场景下优先考虑性能。

掌握这些遍历方法,不仅能写出更优雅的代码,更能避免常见的边界错误。记住:没有 “最好” 的方法,只有 “最适合” 当前场景的方法。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/5 7:56:08

2025 AtomGit 最受欢迎 G-Star 项目 组织名单公示

本次评选活动面向全体 G-Star 认证个人项目、G-Star 认证开源组织。分个人和组织两个赛道&#xff0c;以项目/组织 2025 年末在 AtomGit 平台的各项社区化数据进行积分排名。共 332 个 G-Star 项目、152 个 G-Star 组织参与竞选&#xff0c;最终评选出得分最高的项目和组织共 1…

作者头像 李华
网站建设 2026/6/4 23:22:37

导师推荐!专科生必看9款AI论文网站测评

导师推荐&#xff01;专科生必看9款AI论文网站测评 2026年专科生论文写作工具测评&#xff1a;从功能到体验的深度解析 随着AI技术在学术领域的广泛应用&#xff0c;越来越多的专科生开始借助AI工具提升论文写作效率。然而&#xff0c;面对市场上琳琅满目的AI论文网站&#xff…

作者头像 李华
网站建设 2026/6/10 23:52:02

C 未定义行为

C 未定义行为 引言 C语言作为一种历史悠久且广泛使用的编程语言,拥有强大的功能和灵活性。然而,由于其设计之初并未考虑所有可能的边界情况,C语言中存在一些未定义行为(Undefined Behavior)。这些未定义行为可能导致程序出现不可预测的结果,从而带来安全风险和性能问题…

作者头像 李华
网站建设 2026/6/12 17:45:08

Apipos推荐

作为一名软件开发者&#xff0c;我花了很多时间探索各种工具&#xff0c;以简化我在API开发和测试中的日常工作。Postman 是我一直以来的首选工具&#xff0c;它因其调试和自动化API测试的能力而广受欢迎&#xff0c;几乎成为现代开发者不可或缺的工具。Postman的常见问题然而&…

作者头像 李华
网站建设 2026/6/4 21:23:11

奥偌中心供氧系统工程:技术创新与专业服务的行业典范

在医疗机构现代化建设的进程中&#xff0c;中心供氧系统作为重要的基础设施&#xff0c;其技术水平和服务质量直接影响医疗机构的运行效率和患者安全。在众多业内企业中&#xff0c;奥偌医疗凭借扎实的专业技术和全面的解决方案能力&#xff0c;成为行业内的专业服务商。本文将…

作者头像 李华
网站建设 2026/6/15 8:34:10

进口标致专修全系车型维修手册诊断手册电路图资料库上线更新RCZ 206CC 206GTi 308CC 308SW 407 4008 607 207CC 3008 207SW 208 307CC 307

资料来源&#xff1a;汽修帮手资料库汽修帮手资料库提供各大厂家车型维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表位置等&#xff0c;并长期保持高频率资料更新该车系资料…

作者头像 李华