添加、删除、替换、插入元素的全方法指南

精通 JS 数组操作:添加、删除、替换、插入元素的全方法指南

在 JavaScript 开发中,数组是处理有序数据的核心载体,而「添加、删除、替换、插入元素」是数组最高频的操作场景。新手常陷入 "方法用错、原数组修改失控、性能低效" 的问题 ------ 比如用push替代unshift导致性能问题、用splice时参数写错引发数据错乱、分不清 "是否修改原数组" 的边界。

本文将从「场景分类」「方法拆解」「性能对比」「避坑指南」四个维度,系统讲解 JS 中数组元素增删改插的所有常用方法,结合实战案例和最佳实践,帮你精准选择合适的方法,写出高效且易维护的代码。

一、核心认知:先分清 "是否修改原数组"

在学习具体方法前,必须先明确一个核心原则:JS 数组方法分为「修改原数组」和「返回新数组」两类,这直接决定了代码的副作用和使用场景。

类型 核心特点 常用方法
修改原数组 直接操作原数组,会产生副作用 push、pop、unshift、shift、splice、fill
返回新数组 不修改原数组,返回新数组 concat、slice、map、filter、扩展运算符 (...)

关键建议

  • 若需保留原数组(如状态管理、数据溯源),优先用「返回新数组」的方法;
  • 若仅需操作数据且无需保留原数组,可用「修改原数组」的方法(性能更高)。

二、添加元素:4 类方法覆盖所有场景

添加元素的核心场景分为「尾部添加」「头部添加」「指定位置添加」「批量添加」,不同场景对应不同最优方法:

1. 尾部添加(最常用)

(1)push ():修改原数组,尾部添加一个 / 多个元素

语法array.push(element1, ..., elementN)返回值 :添加后数组的新长度实战示例

javascript

运行

复制代码
const arr = [1, 2, 3];
const newLength = arr.push(4, 5); // 添加多个元素
console.log(arr); // [1, 2, 3, 4, 5](原数组被修改)
console.log(newLength); // 5

优势 :性能最优(数组尾部添加无索引重排),支持批量添加;适用场景:列表追加数据、栈结构(后进先出)的入栈操作。

(2)扩展运算符 (...):返回新数组,尾部添加元素

语法[...原数组, 新元素1, 新元素2]实战示例

javascript

运行

复制代码
const arr = [1, 2, 3];
const newArr = [...arr, 4, 5]; // 不修改原数组
console.log(arr); // [1, 2, 3](原数组不变)
console.log(newArr); // [1, 2, 3, 4, 5]

优势 :无副作用,语法简洁;适用场景:React/Vue 等框架的状态更新(需保持原状态不可变)。

2. 头部添加

(1)unshift ():修改原数组,头部添加一个 / 多个元素

语法array.unshift(element1, ..., elementN)返回值 :添加后数组的新长度实战示例

javascript

运行

复制代码
const arr = [3, 4, 5];
const newLength = arr.unshift(1, 2);
console.log(arr); // [1, 2, 3, 4, 5](原数组被修改)
console.log(newLength); // 5

注意 :头部添加会导致所有元素索引重排,大数据量(10 万 +)场景性能差适用场景:小数据量列表的头部追加、队列结构(先进先出)的入队操作。

(2)扩展运算符 (...):返回新数组,头部添加元素

语法[新元素1, 新元素2, ...原数组]实战示例

javascript

运行

复制代码
const arr = [3, 4, 5];
const newArr = [1, 2, ...arr];
console.log(arr); // [3, 4, 5](原数组不变)
console.log(newArr); // [1, 2, 3, 4, 5]

优势 :相比unshift,大数据量场景性能更优(无索引重排);适用场景:不可变数据的头部添加。

3. 指定位置添加

splice ():修改原数组,任意位置添加元素

splice是数组操作的 "万能方法",支持添加、删除、替换,核心语法:语法array.splice(startIndex, deleteCount, item1, ..., itemN)

  • startIndex:起始位置(负数表示从末尾倒数,如 - 1 表示最后一个元素前);
  • deleteCount:删除元素的数量(设为 0 则仅添加元素);
  • item1...:要添加的元素。

实战示例(指定位置添加)

javascript

运行

复制代码
const arr = [1, 2, 4, 5];
// 在索引2的位置添加元素3(deleteCount=0)
arr.splice(2, 0, 3);
console.log(arr); // [1, 2, 3, 4, 5](原数组被修改)

// 支持批量添加
arr.splice(3, 0, 3.1, 3.2);
console.log(arr); // [1, 2, 3, 3.1, 3.2, 4, 5]

适用场景:任意位置插入元素,尤其是中间位置添加。

4. 批量添加(合并数组)

concat ():返回新数组,合并多个数组 / 元素

语法array.concat(array1, array2, ..., elementN)实战示例

javascript

运行

复制代码
const arr1 = [1, 2];
const arr2 = [3, 4];
// 合并两个数组
const newArr1 = arr1.concat(arr2); 
console.log(newArr1); // [1, 2, 3, 4]

// 合并数组+单个元素
const newArr2 = arr1.concat(arr2, 5);
console.log(newArr2); // [1, 2, 3, 4, 5]

// 原数组不变
console.log(arr1); // [1, 2]
console.log(arr2); // [3, 4]

替代方案 :扩展运算符[...arr1, ...arr2, 5](语法更简洁,推荐)。

三、删除元素:5 种方法适配不同需求

删除元素的核心场景分为「尾部删除」「头部删除」「指定位置删除」「条件删除」「清空数组」:

1. 尾部删除

pop ():修改原数组,删除最后一个元素

语法array.pop()返回值 :被删除的元素(数组为空则返回 undefined)实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
const deletedItem = arr.pop();
console.log(arr); // [1, 2, 3, 4](原数组被修改)
console.log(deletedItem); // 5

优势 :性能最优(无索引重排);适用场景:栈结构的出栈操作、列表尾部删除。

2. 头部删除

shift ():修改原数组,删除第一个元素

语法array.shift()返回值 :被删除的元素(数组为空则返回 undefined)实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
const deletedItem = arr.shift();
console.log(arr); // [2, 3, 4, 5](原数组被修改)
console.log(deletedItem); // 1

注意 :头部删除会导致索引重排,大数据量场景性能差适用场景:小数据量列表的头部删除、队列结构的出队操作。

3. 指定位置删除

(1)splice ():修改原数组,删除指定位置 / 数量的元素

语法array.splice(startIndex, deleteCount)返回值 :包含被删除元素的数组实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 删除索引2的1个元素(元素3)
const deletedItems = arr.splice(2, 1);
console.log(arr); // [1, 2, 4, 5](原数组被修改)
console.log(deletedItems); // [3]

// 删除从索引1开始的2个元素(2、4)
arr.splice(1, 2);
console.log(arr); // [1, 5]
(2)slice ():返回新数组,"间接删除" 元素(截取保留部分)

语法array.slice(startIndex, endIndex)(endIndex 不包含)实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 保留索引0-1的元素(删除索引2及以后)
const newArr = arr.slice(0, 2);
console.log(arr); // [1, 2, 3, 4, 5](原数组不变)
console.log(newArr); // [1, 2]

// 保留除索引2外的所有元素(删除元素3)
const newArr2 = [...arr.slice(0, 2), ...arr.slice(3)];
console.log(newArr2); // [1, 2, 4, 5]

适用场景:不可变数据的指定位置删除(需保留原数组)。

4. 条件删除(过滤元素)

filter ():返回新数组,删除不符合条件的元素

语法array.filter(callback(item, index, array))回调返回值true保留元素,false删除元素实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5, 6];
// 删除偶数(保留奇数)
const oddArr = arr.filter(item => item % 2 !== 0);
console.log(arr); // [1, 2, 3, 4, 5, 6](原数组不变)
console.log(oddArr); // [1, 3, 5]

// 删除值为3的元素
const noThreeArr = arr.filter(item => item !== 3);
console.log(noThreeArr); // [1, 2, 4, 5, 6]

优势 :语义化强,适合按条件批量删除;适用场景:数据筛选、按规则删除元素(如删除状态为失效的列表项)。

5. 清空数组:3 种方法

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];

// 方法1:修改原数组(推荐,性能最优)
arr.length = 0;
console.log(arr); // []

// 方法2:重新赋值(原数组引用丢失)
let arr2 = [1, 2, 3];
arr2 = []; 
console.log(arr2); // []

// 方法3:splice删除所有元素(修改原数组)
arr.splice(0, arr.length);
console.log(arr); // []

选型建议

  • 需保留原数组引用:用arr.length = 0splice
  • 无需保留引用:直接赋值[](最简洁)。

四、替换元素:精准修改指定位置的值

替换元素的核心是 "定位 + 赋值",分为「直接替换」「条件替换」「批量替换」:

1. 直接替换(已知索引)

(1)索引赋值:修改原数组,最简单的替换方式

语法array[index] = 新值实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 替换索引2的元素为30
arr[2] = 30;
console.log(arr); // [1, 2, 30, 4, 5]

注意 :若索引超出数组长度,会创建稀疏数组(如arr[10] = 10,索引 3-9 为 empty),需避免。

(2)splice ():修改原数组,替换指定位置元素

语法array.splice(startIndex, 1, 新值)(deleteCount=1 表示删除 1 个并替换)实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 替换索引2的元素为30
arr.splice(2, 1, 30);
console.log(arr); // [1, 2, 30, 4, 5]

// 批量替换(替换索引1开始的2个元素)
arr.splice(1, 2, 20, 30);
console.log(arr); // [1, 20, 30, 4, 5]

适用场景:替换 + 删除 / 添加结合(如替换的同时插入新元素)。

2. 条件替换(未知索引)

map ():返回新数组,按条件替换元素

语法array.map(callback(item, index, array))回调返回值 :替换后的新值(无需替换则返回原 item)实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 将值为3的元素替换为30,其余不变
const newArr = arr.map(item => item === 3 ? 30 : item);
console.log(arr); // [1, 2, 3, 4, 5](原数组不变)
console.log(newArr); // [1, 2, 30, 4, 5]

// 批量替换:所有偶数乘以2
const doubleEvenArr = arr.map(item => item % 2 === 0 ? item * 2 : item);
console.log(doubleEvenArr); // [1, 4, 3, 8, 5]

优势 :无副作用,语义化强;适用场景:不可变数据的条件替换、批量格式转换。

3. 批量替换(填充值)

fill ():修改原数组,填充指定值到数组

语法array.fill(value, startIndex, endIndex)

  • value:要填充的值;
  • startIndex:起始位置(默认 0);
  • endIndex:结束位置(默认数组长度,不包含)。

实战示例

javascript

运行

复制代码
const arr = [1, 2, 3, 4, 5];
// 替换所有元素为0
arr.fill(0);
console.log(arr); // [0, 0, 0, 0, 0]

// 替换索引1-3的元素为9(endIndex=4,不包含)
const arr2 = [1, 2, 3, 4, 5];
arr2.fill(9, 1, 4);
console.log(arr2); // [1, 9, 9, 9, 5]

适用场景:数组初始化、批量替换固定值。

五、插入元素:本质是 "指定位置添加"

插入元素的核心方法已在 "添加元素" 章节讲解,这里补充 2 个高频场景的最佳实践:

1. 中间位置插入(最常用)

javascript

运行

复制代码
const arr = [1, 2, 4, 5];
// 在元素2和4之间插入3(索引2)
arr.splice(2, 0, 3);
console.log(arr); // [1, 2, 3, 4, 5]

2. 按条件插入(如排序插入)

javascript

运行

复制代码
const arr = [1, 3, 4, 5];
const newItem = 2;
// 找到第一个大于newItem的元素索引,插入其前面
const insertIndex = arr.findIndex(item => item > newItem);
// 若所有元素都小于newItem,插入到末尾
const finalIndex = insertIndex === -1 ? arr.length : insertIndex;
arr.splice(finalIndex, 0, newItem);
console.log(arr); // [1, 2, 3, 4, 5]

六、性能对比与选型决策树

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

操作场景 最优方法 次优方法 避免使用
尾部添加 push 扩展运算符 -
头部添加 扩展运算符 unshift unshift(大数据量)
指定位置删除 splice slice + 扩展运算符 -
条件删除 filter splice(循环) 手动 for 循环删除
直接替换 索引赋值 splice map(仅单元素替换)

2. 选型决策树

预览

查看代码

数组操作

是否需要保留原数组?

用返回新数组的方法:扩展运算符、concat、slice、filter、map

用修改原数组的方法:push、pop、unshift、shift、splice、fill

操作类型?

操作类型?

添加:扩展运算符/concat

删除:filter/slice

替换:map

尾部增删:push/pop

头部增删:unshift/shift(小数据)

指定位置操作:splice

批量替换:fill

复制代码
graph TD
A[数组操作] --> B{是否需要保留原数组?}
B -->|是| C[用返回新数组的方法:扩展运算符、concat、slice、filter、map]
B -->|否| D[用修改原数组的方法:push、pop、unshift、shift、splice、fill]
C --> E{操作类型?}
D --> F{操作类型?}
E --> E1[添加:扩展运算符/concat]
E --> E2[删除:filter/slice]
E --> E3[替换:map]
F --> F1[尾部增删:push/pop]
F --> F2[头部增删:unshift/shift(小数据)]
F --> F3[指定位置操作:splice]
F --> F4[批量替换:fill]

数组操作

是否需要保留原数组?

用返回新数组的方法:扩展运算符、concat、slice、filter、map

用修改原数组的方法:push、pop、unshift、shift、splice、fill

操作类型?

操作类型?

添加:扩展运算符/concat

删除:filter/slice

替换:map

尾部增删:push/pop

头部增删:unshift/shift(小数据)

指定位置操作:splice

批量替换:fill

豆包

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

七、避坑指南(高频错误)

  1. ❌ 用for循环遍历数组时删除元素,导致索引错乱:

    javascript

    运行

    复制代码
    // 错误示例:删除偶数会漏删(索引重排)
    const arr = [1, 2, 3, 4];
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] % 2 === 0) arr.splice(i, 1);
    }
    console.log(arr); // [1, 3, 4](4未被删除)
    
    // 正确示例:反向遍历
    for (let i = arr.length - 1; i >= 0; i--) {
      if (arr[i] % 2 === 0) arr.splice(i, 1);
    }
  2. ❌ 混淆splice的参数顺序(startIndex 在前,deleteCount 在后);

  3. ❌ 用map做无返回值的遍历(应改用forEach);

  4. ❌ 大数据量场景用unshift/shift(应改用扩展运算符或链表结构)。

总结

  1. 数组操作的核心是区分「修改原数组」和「返回新数组」:需保留原数组用扩展运算符 /filter/map,无需保留用 push/pop/splice;
  2. 增删改插的最优方法:尾部用 push/pop,头部小数据用 unshift/shift(大数据用扩展运算符),指定位置用 splice,条件操作用 filter/map;
  3. 避坑关键:避免在正向遍历中删除元素、明确 splice 参数顺序、大数据量场景优先选择无索引重排的方法。

掌握这些方法和最佳实践,能让你在处理数组时既保证性能,又避免常见错误。记住:没有 "万能方法",只有 "最适合当前场景的方法"。

相关推荐
源代码•宸9 小时前
Leetcode—712. 两个字符串的最小ASCII删除和【中等】
开发语言·后端·算法·leetcode·职场和发展·golang·dp
小当家.1059 小时前
JVM八股详解(上部):核心原理与内存管理
java·jvm·学习·面试
qq_316837759 小时前
Element-Plus el-table lazy 自动更新子列表
前端·vue.js·elementui
heartbeat..9 小时前
Spring 声明式事务:原理、使用及失效场景详解
java·spring·面试·事务
无风听海9 小时前
C# 中对象相等性判断的全面解析
开发语言·c#
寻星探路9 小时前
【Python 全栈测开之路】Python 基础语法精讲(三):函数、容器类型与文件处理
java·开发语言·c++·人工智能·python·ai·c#
逑之9 小时前
C语言笔记8:操作符
c语言·开发语言·笔记
xiaolyuh1239 小时前
【XXL-JOB】执行器 Netty服务 & Tomcat 进程+资源共用详解
java·tomcat
无限进步_9 小时前
【C语言&数据结构】相同的树:深入理解二叉树的结构与值比较
c语言·开发语言·数据结构·c++·算法·github·visual studio