救命!数组常用方法居然可以这么记~

62 阅读9分钟

作为前端新手,谁还没被数组的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的对比

特性spliceslice
是否修改原数组✅ 直接修改原数组❌ 不修改原数组,返回新数组
参数含义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()

判断数组“是否包含指定元素”,返回布尔值(最简洁)

  • 小技巧:判断元素是否存在,用includesindexOf更直观(不用判断是否等于-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 本身不会修改数组的结构,但如果在回调里通过下标修改元素,会改变原数组(属于手动修改,非方法本身行为)。


以上就是数组中最常用的方法啦,记住后就再也不怕面试官问到有关数组的方法了

有问题可以在评论区多多交流哦~

如果觉得有用,欢迎点赞收藏,一起加油成长呀🌟