会直接修改原数组的方法有:push()、pop()、unshift()、shift()、splice()、sort()、reverse()、fill();它们均不创建新数组,而是立即改变原数组内容。

哪些 JavaScript 数组方法会直接修改原数组
JavaScript 中有明确的一类数组方法,调用后会**直接改变原数组内容**,而不是返回新数组。这类方法统称为“原地修改(mutating)”方法。如果你在 map、filter 之后发现原数组变了,那大概率是误用了这些方法。
-
push():末尾添加一个或多个元素 -
pop():删除并返回最后一个元素 -
unshift():开头添加一个或多个元素 -
shift():删除并返回第一个元素 -
splice():从指定位置删除、替换或插入元素(最常被误判) -
sort():按字符串 Unicode 码点排序(注意:不是数值排序) -
reverse():反转数组顺序 -
fill():用指定值填充整个或部分数组
它们的共同特点是:不创建新数组,操作立即反映在原引用上。比如:
const arr = [1, 2, 3]; arr.push(4); console.log(arr); // [1, 2, 3, 4] —— 原数组已变
为什么 splice() 是最容易踩坑的原地方法
splice() 功能强大但副作用明显:它既改原数组,又返回被删元素组成的数组,容易让人误以为“有返回值 = 不改原数组”。实际它一定会修改原数组,哪怕只读不删(例如 arr.splice(0, 0, 'x') 插入空项也会触发修改)。
- 删除:
arr.splice(1, 2)→ 删除索引 1 开始的 2 个元素 - 替换:
arr.splice(1, 2, 'a', 'b')→ 删掉 2 个,插入 'a' 和 'b' - 纯插入:
arr.splice(2, 0, 'x', 'y')→ 在索引 2 处插入,不删任何元素
所有情况都直接修改 arr。如果只是想取子数组,请用 slice()(无副作用)。
立即学习“Java免费学习笔记(深入)”;
sort() 的隐式类型转换陷阱
sort() 默认把元素转成字符串再比较,所以 [10, 2, 30].sort() 结果是 [10, 2, 30](因为 '10' 为 true)。这不仅改变原数组,还很可能不是你想要的结果。
- 数值升序:
arr.sort((a, b) => a - b) - 数值降序:
arr.sort((a, b) => b - a) - 字符串忽略大小写:
arr.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
只要调用了 sort(),无论传不传比较函数,原数组都会被重排。
如何安全地避免意外修改原数组
多数场景下,你真正需要的是“不可变操作”——保留原数组不变,生成新数组。这时候必须显式拷贝:
- 浅拷贝数组:
[...arr]、arr.slice()、Array.from(arr) - 链式操作前先拷贝:
[...arr].map(x => x * 2).filter(x => x > 5) - 对象数组需深拷贝?
JSON.parse(JSON.stringify(arr))仅适用于纯数据;复杂结构建议用structuredClone()(现代环境)或专用库
特别注意:concat()、map()、filter()、flatMap()、slice() 这些方法本身不改原数组,但如果你对它们的返回结果再次调用 push() 或 splice(),那就又回到原地修改了。











