作为前端新手,谁还没被数组的n种方法搞晕过?push、pop、splice、map……记了又忘,忘了又记,仿佛陷入无限循环😭
今天就把数组常用方法按「增删改查排转迭」7大分类,用最接地气的类比+实用场景,一次性讲明白,以后写代码再也不用翻文档!
一、增:给数组“添新成员”
数组 = 收纳盒,“增”就是往盒子里放新东西,不同方法放的位置和方式不一样,按需选择就好~
1. push()
从“盒子底部”加东西,返回新长度
- 类比:往书包最里面塞书,塞完告诉你现在有几本书。
- 小技巧:可以一次性加多个值,比如
push(4,5,6),不用重复调用。
const arr = [1, 2];
arr.push(5); // 返回 3,arr 变为 [1, 2, 5]
arr.push(4, 7, 9); // 返回 6,arr 变为 [1, 2, 5, 4, 7, 9]
2. unshift()
从“盒子顶部”加东西,返回新长度
- 类比:往书包最外面放笔记本,优先拿取。
- 注意:频繁用
unshift会影响性能(数组要整体后移),数据量大时慎用~
const arr = [2, 3];
arr.unshift(1); // 返回 3,arr 变为 [1, 2, 3]
arr.unshift(9, 7); // 返回 5,arr 变为 [9, 7, 1, 2, 3]
3. splice(位置, 0, 新增值)
在“盒子中间任意位置”加东西,返回空数组
- 重点:第二个参数是删除长度,传
0就是“只加不删”,所以返回的删除元素的数组就是空数组! - 注意:该方法会改变原数组!
- 参数使用:
- 第一个(index):起始位置的下标,新增的元素会从该位置放进去,原来的元素后移。
- 第二个(howmany):删除长度,作为“增”方法一定要写“0”,否则会将起始位置至末尾的所有元素删除
- 第三个(item):要添加到数组的新元素,可有多个,直接接着写在一起就行。
const arr = [1, 3];
arr.splice(1, 0, 2); // arr 变为 [1, 2, 3]
arr.splice(2, 0, 2.5, 2.8); // arr 变为 [1, 2, 2.5, 2.8, 3]
4. concat()
“合并两个盒子”,不改变原数组
- 类比:把两个书包的东西合并成一个新书包,原来的两个书包不变。
const arr1 = [1, 2];
const arr2 = [3, 4];
const newArr = arr1.concat(arr2); // [1, 2, 3, 4]
const newArr2 = arr1.concat(arr2, [5, 6]); // [1, 2, 3, 4, 5, 6]
二、删:给数组“减减负”
删元素和加元素对应,有从头部删、尾部删、中间删,还有“过滤式删除”,重点区分「是否改变原数组」!
1. pop()
从“盒子底部”删东西,返回被删的元素
- 类比:把书包最里面的书拿出来,告诉你拿的是哪本。
const arr = [1, 2, 3];
const deleted = arr.pop(); // deleted 为 3,arr 变为 [1, 2]
2. shift()
从“盒子顶部”删东西,返回被删的元素
- 类比:把书包最外面的笔记本拿出来,
- 注意:和
unshift一样,频繁shift会影响性能。
const arr = [1, 2, 3];
const deleted = arr.shift(); // deleted 为 1,arr 变为 [2, 3]
3. slice(起始索引, 结束索引)
在“中间任意位置”截取元素,返回所截的元素组成的数组,不改变原数组,间接实现删除
- 类比:从一排魔法书中连续抽出几本,你拿到了书,但是书柜上的书还在那里。
- 注意:第二个参数不包含本身!
const arr = [6, 5, 4, 3, 2, 1];
const newArr = arr.slice(1, 4); // 截取索引1到4(不含4),返回 [5, 4, 3]
4. filter()
“过滤式删除”,保留符合条件的元素,不改变原数组
- 类比:筛选书包里的数学书,把其他书去掉,得到一个新的只有数学书的书包。
- 高频场景:筛选列表数据、过滤无效值(比如
filter(item => item)过滤空值)。
const scores = [58, 65, 90, 88, 45];
// 筛掉不及格的(保留≥60)
const pass = scores.filter(score => score >= 60);
console.log(pass); // [65, 90, 88]
补充:splice与slice的对比
| 特性 | splice | slice |
|---|---|---|
| 是否修改原数组 | ✅ 直接修改原数组 | ❌ 不修改原数组,返回新数组 |
| 参数含义 | index(起始索引), howmany(删除个数), item(新增元素) | start(起始索引), end(结束索引,不包含) |
| 返回值 | 被删除的元素组成的数组(无删除则为空) | 截取的新数组(从 start 到 end-1) |
| 索引支持负数 | ✅(表示从末尾倒数) | ✅(表示从末尾倒数) |
| 常用场景 | 删除 / 添加 / 替换原数组元素 | 截取数组片段(不影响原数组) |
三、改:给数组“换内容”
数组改内容,最常用的就是「下标直接改」,简单粗暴,还有一个小众但实用的copyWithin,偶尔能救急~
1. 下标修改(最常用)
直接定位“盒子里的位置”,替换内容
const names = ["张三", "李四", "王五"];
// 把“李四”改成“李老四”
names[1] = "李老四";
console.log(names); // ["张三", "李老四", "王五"]
2. copyWithin(目标位置, 起始位置, 停止位置)
用数组自身的元素“替换”自身内容,改变原数组
- 小众但实用:需要重复使用数组内元素时,不用额外写逻辑,直接用它。
const nums = [9, 8, 7, 6, 5];
// 把索引0-2(不含)的元素(9, 8)复制到索引3的位置
nums.copyWithin(3, 0, 2);
console.log(nums); // [9, 8, 7, 9, 8](6和5被替换成9和8)
四、查:在数组里“找东西”
开发中经常需要“找某个元素在不在数组里”“找元素的位置”,这5种方法覆盖所有查找场景,再也不用循环遍历!
1. find()
找“第一个符合条件”的元素,找到返回元素,找不到返回undefined
- 比如
[1,2,3,4].find(item => item % 2 === 0),返回2(第一个偶数)。
const arr = [{ id: 1, name: '张三' }, { id: 2, name: '李四' }];
const target = arr.find(item => item.id === 2);
console.log(target); // { id: 2, name: '李四' }
2. findIndex()
找“第一个符合条件”的元素的索引,找到返回索引,找不到返回-1
- 和find对应,比如
[1,2,3,4].findIndex(item => item % 2 === 0),返回1(元素2的索引)。
3. findLastIndex()
找“最后一个符合条件”的元素的索引,和findIndex相反【也就是从右往左找】
- 比如
[1,2,3,4].findLastIndex(item => item % 2 === 0),返回3(元素4的索引)。 - 注意:找的顺序是从右往左,但是下标顺序还是自左向右的0,1,2,...
const arr = [1, 2, 3, 2];
console.log(arr.findIndex(item => item === 2)); // 1
console.log(arr.findLastIndex(item => item === 2)); // 3
4. indexOf()
找“指定元素”的第一个索引,找不到返回-1(不支持函数条件)
const arr = [1, 2, 3, 2, 3];
console.log(arr.indexOf(3)); // 2 (找到就返回所找元素的索引)
console.log(arr.indexOf(4)); // -1 (找不到就返回-1)
5. includes()
判断数组“是否包含指定元素”,返回布尔值(最简洁)
- 小技巧:判断元素是否存在,用
includes比indexOf更直观(不用判断是否等于-1)。
const arr = [1, 2, 3];
console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false
五、排序:给数组“排排队”
数组排序很常用,但sort有个坑,新手很容易踩,一定要注意!
1. sort()
默认按“字符串Unicode码”排序,改变原数组
- 正确用法:传排序函数,比如传入
(a,b) => a - b(升序),(a,b) => b - a(降序)。
// 坑点:数字排序直接.sort()
const arr = [10,2,3].sort()
console.log(arr); // [10, 2, 3] (未正确排序,因为10的第一个字符“1”比“2”小!)
// 数值升序
const arr1 = [3, 1, 2];
arr1.sort((a, b) => a - b);
console.log(arr1); // [1, 2, 3]
// 数值降序
const arr2 = [3, 1, 2];
arr2.sort((a, b) => b - a);
console.log(arr2); // [3, 2, 1]
2. reverse()
数组“反转顺序”,改变原数组
- 比如
[1,2,3].reverse(),结果是[3,2,1],简单直接。
const arr1 = [1, 2, 3];
arr1.reverse();
console.log(arr1); // [3, 2, 1]
3. toReversed()
反转数组,不改变原数组(ES6新增,更安全)
const arr2 = [1, 2, 3];
const newArr = arr2.toReversed();
console.log(newArr); // [3, 2, 1]
console.log(arr2); // [1, 2, 3]
六、转换:数组“变模样”
有时候需要把数组转换成字符串,方便展示或传输,这两种方法足够用了~
1. toString()
把数组转换成“逗号分隔”的字符串,不改变原数组
- 比如
[1,2,3].toString(),返回"1,2,3"。
const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
2. join(“分隔符”)
把数组转换成“指定分隔符”的字符串,比toString更灵活
- 高频场景:拼接标签、拼接接口参数(比如
ids.join(','))。
const arr = [1, 2, 3];
console.log(arr.join('-')); // "1-2-3"
console.log(arr.join('')); // "123"
七、迭代:遍历数组“做操作”
迭代就是“逐个访问数组元素,做对应的操作”,不同方法的返回值和用途不一样,别用混啦!
1. forEach(元素,下标)
单纯“遍历数组”,没有返回值(常用语渲染列表、执行副作用)
- 比如
[1,2,3].forEach(item => console.log(item)),只会打印1、2、3,没有返回值(返回undefined)。
const arr = [1, 2, 3];
arr.forEach((item, index) => { console.log(`索引${index}的值:${item}`); });
// 输出:
// 索引0的值:1
// 索引1的值:2
// 索引2的值:3
2. map()
遍历数组,“返回一个新数组”(每个元素经过处理),不改变原数组
- 高频场景:列表数据转换(比如把数组里的id提取出来,
list.map(item => item.id))。
const arr = [1, 2, 3];
const newArr = arr.map(item => item * 2); // 将每个元素都放大两倍
console.log(newArr); // [2, 4, 6]
3. reduce(计算结果,当前元素)
“累加/汇总”数组,返回一个最终值(最强大,灵活度最高)
- 高频场景:求数组总和,用来去重、扁平化数组。
// 求和
const arr = [1, 2, 3];
const sum = arr.reduce((total, item) => total + item, 0);
console.log(sum); // 6
4. some()
判断数组“是否有至少一个元素符合条件”,返回布尔值。
const arr = [1, 2, 3];
const hasBig = arr.some(item => item > 2); // 判断arr中是否有大于2的元素
console.log(hasBig); // true (因为有 3 > 2)
5. every()
判断数组“所有元素都符合条件”,返回布尔值
const arr = [1, 2, 3];
const allBig = arr.every(item => item > 2); // 判断arr中是否所以元素都大于2
console.log(allBig); // false
💡最后:方法总结
| 方法分类 | 具体方法 | 是否修改原数组 | 核心用途 |
|---|---|---|---|
| 增 | push、unshift、splice | ✅ 是 | 尾部 / 头部 / 指定位置添加元素 |
| concat | ❌ 否 | 合并多个数组(返回新数组) | |
| 删 | pop、shift、splice | ✅ 是 | 尾部 / 头部 / 指定位置删除元素 |
| slice、filter | ❌ 否 | 截取 / 过滤元素(返回新数组) | |
| 改 | 下标修改、copyWithin | ✅ 是 | 直接修改 / 批量复制替换元素 |
| 查 | find、findIndex、findLastIndex | ❌ 否 | 查找符合条件的元素 / 索引 |
| indexOf、includes | ❌ 否 | 判断元素位置 / 是否存在 | |
| 排序 | sort、reverse | ✅ 是 | 排序 / 反转数组(修改原数组) |
| toReversed | ❌ 否 | 反转数组(返回新数组) | |
| 转换 | toString、join | ❌ 否 | 数组转字符串(自定义分隔符) |
| 迭代 | forEach | ✅ 是(注) | 遍历执行操作(无返回值) |
| map、reduce、some、every | ❌ 否 | 遍历处理 / 累加 / 条件判断 |
📌 注:forEach 本身不会修改数组的结构,但如果在回调里通过下标修改元素,会改变原数组(属于手动修改,非方法本身行为)。
以上就是数组中最常用的方法啦,记住后就再也不怕面试官问到有关数组的方法了
有问题可以在评论区多多交流哦~
如果觉得有用,欢迎点赞收藏,一起加油成长呀🌟