25个每个开发人员都应该掌握的JavaScript 数组方法
myzbx 2025-09-18 23:47 2 浏览
掌握 JavaScript 数组方法是提升开发效率、写出简洁可维护代码的核心能力。以下将 25 个核心数组方法按「遍历查询」「转换处理」「修改操作」「创建合并」四大类分类讲解,每个方法包含作用、语法、参数、返回值、示例,并标注关键注意点(如是否改变原数组)。
一、遍历与查询类(8 个)
这类方法主要用于遍历数组、查询元素或判断条件,大部分不改变原数组。
1.forEach()- 基础遍历
- 作用:遍历数组,对每个元素执行回调函数(无返回值,仅用于 “执行操作”)。
- 语法:array.forEach(callback(currentValue, index, array), thisArg)
- 参数:
- callback:必选,每个元素执行的函数,接收 3 个参数:
- currentValue:当前遍历的元素index:当前元素的索引(可选)
- array:原数组(可选)
- thisArg:可选,指定 callback 中的 this 指向。
- 返回值:undefined(无返回值)
- 注意:无法通过 break/continue 中断遍历(除了抛出异常)。
const users = [{ name: 'A', age: 20 }, { name: 'B', age: 25 }];
users.forEach(user => {
console.log(`${user.name} 的年龄是 ${user.age}`);
});
// 输出:A 的年龄是 20;B 的年龄是 25
2.map()- 遍历并转换
- 作用:遍历数组,对每个元素执行回调函数,返回新数组(新数组长度与原数组一致)。
- 语法:array.map(callback(currentValue, index, array), thisArg)
- 返回值:新数组(每个元素是 callback 的返回值)
- 注意:不改变原数组,若无需返回新数组,用 forEach 更合适。
- 示例:将用户年龄加 1
const newUsers = users.map(user => ({
...user,
age: user.age + 1 // 原数组元素不变,返回新对象
}));
// newUsers: [{name:'A',age:21}, {name:'B',age:26}]
3.filter()- 筛选元素
- 作用:遍历数组,筛选出满足 callback 条件(返回 true)的元素,返回新数组。
- 语法:array.filter(callback(currentValue, index, array), thisArg)
- 返回值:新数组(仅包含满足条件的元素,长度可能小于原数组)
- 示例:筛选成年用户(age ≥ 18)
const adultUsers = users.filter(user => user.age >= 18);
4.find()- 查找第一个匹配元素
- 作用:遍历数组,返回第一个满足 callback 条件的元素;若无匹配,返回 undefined。
- 语法:array.find(callback(currentValue, index, array), thisArg)
- 返回值:匹配的元素(或 undefined)
- 注意:找到后立即停止遍历(效率高),不改变原数组。
- 示例:查找名字为「A」的用户
const userA = users.find(user => user.name === 'A');
5.findIndex()- 查找第一个匹配元素的索引
- 作用:与 find() 类似,但返回第一个匹配元素的索引;若无匹配,返回 -1。
- 语法:array.findIndex(callback(currentValue, index, array), thisArg)
- 返回值:匹配元素的索引(或 -1)
- 示例:查找年龄为 25 的用户索引
const index = users.findIndex(user => user.age === 25); // 1
6.some()- 判断 “是否有一个” 满足条件
- 作用:判断数组中是否存在至少一个元素满足 callback 条件,返回布尔值。
- 语法:array.some(callback(currentValue, index, array), thisArg)
- 返回值:true(有匹配)/ false(无匹配)
- 注意:找到一个满足条件的元素后立即停止遍历(短路逻辑)。
- 示例:判断是否有未成年用户
const hasMinor = users.some(user => user.age < 18); // false
7.every()- 判断 “是否全部” 满足条件
- 作用:判断数组中所有元素是否都满足 callback 条件,返回布尔值。
- 语法:array.every(callback(currentValue, index, array), thisArg)
- 返回值:true(全部满足)/ false(至少一个不满足)
- 注意:只要有一个元素不满足,立即停止遍历(短路逻辑)。
- 示例:判断所有用户是否都是成年人
const allAdult = users.every(user => user.age >= 18); // true
8.includes()- 判断是否包含指定元素
- 作用:判断数组是否包含指定元素,返回布尔值(简单判断,无需回调)。
- 语法:array.includes(searchElement, fromIndex)
- 参数:searchElement:必选,要查找的元素fromIndex:可选,从哪个索引开始查找(默认 0,负数表示从末尾倒数)
- 返回值:true(包含)/ false(不包含)
- 注意:使用「严格相等(===)」判断,无法判断对象(需用 find)。
- 示例:
const nums = [1, 2, 3];
nums.includes(2); // true
nums.includes(4); // false
nums.includes(1, 1); // false(从索引1开始找1,没有)
二、转换与聚合类(5 个)
这类方法用于将数组转换为其他格式(如值、字符串、扁平数组)或聚合数据。
9.reduce()- 聚合为单个值
- 作用:遍历数组,通过回调函数将数组元素 “累积” 为单个值(如求和、分组、去重),功能极强。
- 语法:array.reduce(callback(accumulator, currentValue, index, array), initialValue)
- 参数:
- callback:必选,累积函数,接收 4 个参数:
- accumulator:累积结果(上一次回调的返回值,或 initialValue)
- currentValue:当前元素index:当前索引(可选)
- array:原数组(可选)
- initialValue:可选,
- accumulator 的初始值;若无,默认用数组第一个元素(此时数组为空会报错)。
- 返回值:最终的累积结果
- 示例:
- 求和:const sum = [1,2,3].reduce((acc, cur) => acc + cur, 0); // 6
- 数组去重:const unique = [1,2,2,3].reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
- 分组(按年龄分组用户):
const grouped = users.reduce((acc, cur) => {
const key = cur.age; // 按年龄作为键
acc[key] = acc[key] ? [...acc[key], cur] : [cur];
return acc;
}, {});
10.flat()- 扁平化数组
- 作用:将嵌套的数组 “扁平化” 为一维或指定深度的数组,返回新数组。
- 语法:array.flat(depth)
- 参数:depth:可选,扁平化深度(默认 1,Infinity 表示完全扁平化)。
- 返回值:扁平化后的新数组
- 注意:不改变原数组,忽略空元素(如 [1, [2, ,3]].flat() → [1,2,3])。
- 示例:
const nested = [1, [2, [3, 4]]];
nested.flat(); // [1,2,[3,4]](深度1)
nested.flat(2); // [1,2,3,4](深度2)
nested.flat(Infinity); // [1,2,3,4](完全扁平化)
11.flatMap()- 映射后扁平化
- 作用:先执行 map() 转换,再对结果执行 flat(1) 扁平化,返回新数组(等价于 map().flat(1),但效率更高)。
- 语法:array.flatMap(callback(currentValue, index, array), thisArg)
- 返回值:映射 + 扁平化后的新数组
- 示例:将用户的 “技能数组” 展开为单个技能列表
const usersWithSkills = [
{ name: 'A', skills: ['JS', 'CSS'] },
{ name: 'B', skills: ['HTML', 'React'] }
];
const allSkills = usersWithSkills.flatMap(user => user.skills);
// allSkills: ['JS', 'CSS', 'HTML', 'React']
12.join()- 数组转字符串
- 作用:将数组元素连接为一个字符串,返回该字符串。
- 语法:array.join(separator)
- 参数:separator:可选,连接符(默认是逗号 ,,传空字符串 '' 则无间隔)。
- 返回值:连接后的字符串
- 示例:
const fruits = ['苹果', '香蕉', '橙子'];
fruits.join(); // "苹果,香蕉,橙子"
fruits.join('|'); // "苹果|香蕉|橙子"
13.toString()- 数组转字符串(简化版)
- 作用:将数组转为字符串,等价于 join(',')(无参数可选)。
- 语法:array.toString()
- 返回值:字符串
- 示例:
[1,2,3].toString(); // "1,2,3"
三、修改与排序类(7 个)
这类方法会改变原数组(需注意副作用,若需不可变操作,可先复制数组)。
14.push()- 末尾添加元素
- 作用:向数组末尾添加一个或多个元素,返回新数组的长度。
- 语法:array.push(element1, element2, ...)
- 返回值:新数组的长度
- 注意:改变原数组,若需不可变操作,用 [...array, newElement]。
- 示例:
const nums = [1,2];
const len = nums.push(3,4); // len = 4
// nums: [1,2,3,4]
15.pop()- 末尾删除元素
- 作用:删除数组最后一个元素,返回被删除的元素。
- 语法:array.pop()
- 返回值:被删除的元素(若数组为空,返回 undefined)
- 注意:改变原数组,效率高(无需移动其他元素)。
- 示例:
const nums = [1,2,3];
const deleted = nums.pop(); // deleted = 3
// nums: [1,2]
16.unshift()- 开头添加元素
- 作用:向数组开头添加一个或多个元素,返回新数组的长度。
- 语法:array.unshift(element1, element2, ...)
- 返回值:新数组的长度
- 注意:改变原数组,效率低(需移动所有现有元素)。
- 示例:
const nums = [3,4];
const len = nums.unshift(1,2); // len = 4
// nums: [1,2,3,4]
17.shift()- 开头删除元素
- 作用:删除数组第一个元素,返回被删除的元素。
- 语法:array.shift()
- 返回值:被删除的元素(若数组为空,返回 undefined)
- 注意:改变原数组,效率低(需移动所有现有元素)。
- 示例:
const nums = [1,2,3];
const deleted = nums.shift(); // deleted = 1
// nums: [2,3]
18.splice()- 插入 / 删除 / 替换元素
- 作用:对数组进行插入、删除、替换操作(功能最灵活,但也最容易出错)。
- 语法:array.splice(start, deleteCount, item1, item2, ...)
- 参数:
- start:必选,操作的起始索引(负数表示从末尾倒数)。
- deleteCount:必选,要删除的元素个数(0 表示不删除)。
- item1...:可选,要插入的元素(在 start 位置后插入)。
- 返回值:被删除元素组成的数组(若未删除,返回空数组)
- 注意:改变原数组,需谨慎使用(建议先复制数组再操作)。
- 示例:
const nums = [1,2,3,4,5];
// 1. 删除:从索引2开始,删除2个元素
nums.splice(2, 2); // 返回 [3,4],nums 变为 [1,2,5]
// 2. 替换:从索引1开始,删除1个元素,插入6
nums.splice(1, 1, 6); // 返回 [2],nums 变为 [1,6,5]
// 3. 插入:从索引2开始,删除0个元素,插入7,8
nums.splice(2, 0, 7, 8); // 返回 [],nums 变为 [1,6,7,8,5]
19.sort()- 排序数组
- 作用:对数组元素进行排序,返回排序后的数组(改变原数组)。
- 语法:array.sort(compareFunction)
- 参数:
- compareFunction(a, b):可选,排序规则函数:
- 若 compareFunction(a,b) < 0:a 排在 b 前面。
- 若 compareFunction(a,b) === 0:a 和 b 位置不变。
- 若 compareFunction(a,b) > 0:a 排在 b 后面。
- 注意:
- 默认按「字符串 Unicode 码」排序(如 [10,2].sort() → [10,2],因为 '10' < '2')。
- 必须传 compareFunction 才能正确排序数字。
- 示例:
const nums = [3,1,4,1,5];
// 升序排序(数字)
nums.sort((a, b) => a - b); // [1,1,3,4,5]
// 降序排序(数字)
nums.sort((a, b) => b - a); // [5,4,3,1,1]
// 按用户年龄升序排序
users.sort((a, b) => a.age - b.age);
20.reverse()- 反转数组
- 作用:反转数组元素的顺序,返回反转后的数组(改变原数组)。
- 语法:array.reverse()
- 返回值:反转后的原数组
- 示例:
const nums = [1,2,3];
nums.reverse(); // 返回 [3,2,1],nums 变为 [3,2,1]
四、创建与合并类(5 个)
这类方法用于创建新数组或合并多个数组,不改变原数组。
21.slice()- 截取数组(创建子数组)
- 作用:从原数组中截取指定范围的元素,返回新数组(不改变原数组)。
- 语法:array.slice(start, end)
- 参数:
- start:可选,起始索引(默认 0,负数表示从末尾倒数)。
- end:可选,结束索引(不包含该索引,默认数组长度)。
- 返回值:截取的子数组(若 start >= end,返回空数组)
- 注意:与 splice() 区别:slice 不改变原数组,splice 改变原数组。
- 示例:
const nums = [1,2,3,4,5];
nums.slice(1, 3); // [2,3](从索引1到3,不包含3)
nums.slice(2); // [3,4,5](从索引2到末尾)
nums.slice(-2); // [4,5](从末尾倒数2个元素)
22.concat()- 合并数组
- 作用:合并两个或多个数组,返回新数组(不改变原数组)。
- 语法:array1.concat(array2, array3, ..., valueN)
- 参数:可传数组或单个值(单个值会直接加入新数组)。
- 返回值:合并后的新数组
- 注意:ES6 后常用扩展运算符 [...arr1, ...arr2] 替代(更简洁)。
- 示例:
const a = [1,2];
const b = [3,4];
const c = a.concat(b, 5); // [1,2,3,4,5]
// 等价于:const c = [...a, ...b, 5];
23.Array.from()- 从类数组 / 可迭代对象创建数组
- 作用:将「类数组对象」(如 arguments、DOM 节点列表)或「可迭代对象」(如 Set、Map)转换为真正的数组。
- 语法:Array.from(arrayLike, mapFn, thisArg)
- 参数:
- arrayLike:必选,要转换的类数组 / 可迭代对象。
- mapFn:可选,类似 map() 的回调函数(转换时同步处理元素)。
- thisArg:可选,mapFn 中的 this 指向。
- 返回值:新数组
- 示例:
// 1. 类数组(arguments)转数组
function sum() {
return Array.from(arguments).reduce((acc, cur) => acc + cur, 0);
}
sum(1,2,3); // 6
// 2. Set 转数组(去重)
const set = new Set([1,2,2,3]);
Array.from(set); // [1,2,3]
// 3. 转换时处理元素(等价于 Array.from(set).map(x => x*2))
Array.from(set, x => x * 2); // [2,4,6]
24.Array.of()- 创建指定元素的数组
- 作用:创建一个包含指定元素的数组(解决 new Array() 的歧义问题)。
- 语法:Array.of(element1, element2, ...)
- 返回值:新数组
- 注意:与 new Array() 的区别:new Array(3) → 创建长度为 3 的空数组(无元素)。Array.of(3) → 创建 [3](包含元素 3)。
- 示例:
Array.of(1,2,3); // [1,2,3]
Array.of(5); // [5]
new Array(5); // [empty × 5](空数组,长度5)
25.at()- 通过索引访问元素(支持负索引)
- 作用:通过索引访问数组元素,支持负索引(-1 表示最后一个元素,-2 表示倒数第二个,以此类推)。
- 语法:array.at(index)
- 参数:index:索引(正数 / 负数,默认 0)。
- 返回值:指定索引的元素(若索引超出范围,返回 undefined)
- 注意:替代传统的 array[index](传统方式不支持负索引,如 array[-1] 会返回 undefined)。
- 示例:
const nums = [1,2,3,4];
nums.at(0); // 1(第一个元素)
nums.at(-1); // 4(最后一个元素)
nums.at(-2); // 3(倒数第二个元素)
nums.at(10); // undefined(索引超出范围)
总结:核心使用原则
- 优先避免改变原数组:若需不可变操作,用 map/filter/slice/concat 或扩展运算符 [...arr],减少副作用。
- 按需选择方法:需返回新数组 → map/filter/slice/concat。需聚合值 → reduce(求和、分组、去重)。需查找元素 → find(元素)/findIndex(索引)/includes(简单判断)。需判断条件 → some(任一满足)/every(全部满足)。
- 注意效率:push/pop 效率高于 unshift/shift(后者需移动元素);find/some/every 找到结果后立即停止遍历(短路逻辑)。
掌握这些方法,能大幅减少手写循环的代码量,让逻辑更清晰,同时提升代码的可读性和可维护性。
相关推荐
- vue:生命周期钩子函数及顺序_列举出5个vue中常用的生命周期钩子函数
-
一、vue的钩子相关顺序Vue实例有一个完整的生命周期,在newVue()后,会初始化数据,如下://初始化的入口,各种初始化工作initMixin(Vue);//数据绑定的核心方法,包括常用...
- 最长递增子序列:从经典算法到 Vue3 运行时核心优化
-
最长递增子序列(LongestIncreasingSubsequence,LIS)正悄然成为性能分水岭。它不仅是面试的高频考点,更是Vue3快速Diff算法赖以实现O(nlogn)...
- 十分钟掌握Vue 3性能优化:实战技巧与避坑指南
-
「为什么我的Vue应用越做越卡?」这是最近团队新人最常问的问题。本文将从真实电商项目出发,手把手教你用Vue3的现代特性实现性能飞跃,文末还准备了可复用的优化检查清单!一、先看疗效:优化前后对比优...
- JavaScript学习 -- 文本节点_html 文本节点
-
什么是文本节点在HTML文档中,文本节点是一种特殊的dom节点,它包含文本内容,没有任何标记或属性。<p>这是一段文本节点</p>在上面的代码中,<p>元素包含了...
- JavaScript中this指向各种场景_javascript的this指向
-
在JavaScript中,this的指向是一个核心概念,其值取决于函数的调用方式,而非定义位置(箭头函数除外)。以下是this指向的常见场景及具体说明:1.全局作用域中的this在全局作用域(非...
- v-if和v-for的优先级是什么?_v-if和v-for的区别,什么时候用
-
#一、作用v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true值的时候被渲染v-for指令基于一个数组来渲染一个列表。v-for指令需要使用iteminitems...
- Vue插槽(Slot)深度解析:从匿名到作用域的组件复用革命
-
在Vue组件化开发中,内容分发始终是核心挑战之一。当我们需要让组件既能保持结构复用,又能灵活定制局部内容时,插槽(Slot)机制应运而生。从基础的匿名插槽到复杂的作用域插槽,Vue的插槽系统逐步解决了...
- 手摸手带你解决AI应用开发中Markdown渲染问题
-
使用Markdown-It+VueRender实现安全可控的Markdown渲染在前端项目中,Markdown的渲染经常使用markdown-it。它功能丰富、插件多,但默认的渲染方...
- Vue3 新趋势:10 个最强 X 操作!_vue.3
-
Vue3为前端开发带来了诸多革新,它不仅提升了性能,还提供了更简洁、更强大的API。以下是十个最值得学习和使用的Vue3API,它们将助力你的开发工作迈向新高度。浅层响应式API:shall...
- 25个React最佳实践小技巧_reactor设计模式
-
以下是25个React开发中实用的最佳实践与小技巧,覆盖组件设计、状态管理、性能优化、代码规范、错误处理等核心场景,每个技巧均附示例和核心原因,帮助你写出更高效、可维护的React代码。一...
- javascript函数的call、apply和bind的原理及作用详解
-
javascript函数的call、apply和bind本质是用来实现继承的,专业点说法就是改变函数体内部this的指向,当一个对象没有某个功能时,就可以用这3个来从有相关功能的对象里借用过来...
- 简单介绍一下前端各框架中的模板标签
-
在各大前端框架、小程序中,此类标签的作用主要是用来帮助我们包裹多个元素。在浏览器实际渲染中会将其移除只渲染其包裹的DOM元素,所以说不会增加额外的DOM节点在小程序中使用小程序中的模板标签是<...
- 面试官问我,后端一次性返回十万条数据,前端应该怎么处理 ?
-
问题描述面试官:后端一次性返回10万条数据给你,你如何处理?我:歪嘴一笑,马上给后端发送一百万次请求,干蹦他的服务器,让他给爷哭!问题考察点性能优化意识(能否识别出“10万条数据”会导致性能问题?是...
- React系列十 - 高阶组件以及组件补充
-
源自:coderwhy一.高阶组件1.1.认识高阶组件什么是高阶组件呢?相信很多同学都听说过,也用过高阶函数,它们非常相似,所以我们可以先来回顾一下什么是高阶函数。高阶函数的维基百科定义:至少...
- 从0开始写一个虚拟滚动组件_虚拟滚动原理
-
如果一个页面有1W+条数据,该怎么渲染比较好。不管是在我们的实际项目开发中还是在面试的过程中都会遇到类似的问题。相信很多同学会想到分页。当然这也是最传统也是最保底的解决方案了。如果有开发过electr...
- 一周热门
- 最近发表
-
- vue:生命周期钩子函数及顺序_列举出5个vue中常用的生命周期钩子函数
- 最长递增子序列:从经典算法到 Vue3 运行时核心优化
- 十分钟掌握Vue 3性能优化:实战技巧与避坑指南
- JavaScript学习 -- 文本节点_html 文本节点
- JavaScript中this指向各种场景_javascript的this指向
- v-if和v-for的优先级是什么?_v-if和v-for的区别,什么时候用
- Vue插槽(Slot)深度解析:从匿名到作用域的组件复用革命
- 手摸手带你解决AI应用开发中Markdown渲染问题
- Vue3 新趋势:10 个最强 X 操作!_vue.3
- 25个React最佳实践小技巧_reactor设计模式
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)