25个每个开发人员都应该掌握的JavaScript 数组方法
掌握 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 找到结果后立即停止遍历(短路逻辑)。
掌握这些方法,能大幅减少手写循环的代码量,让逻辑更清晰,同时提升代码的可读性和可维护性。