javascript如何操作数组_哪些方法可以改变原数组

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

哪些 JavaScript 数组方法会直接修改原数组

JavaScript 中有明确的一类数组方法,调用后会**直接改变原数组内容**,而不是返回新数组。这类方法统称为“原地修改(mutating)”方法。如果你在 mapfilter 之后发现原数组变了,那大概率是误用了这些方法。

  • 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()(无副作用)。

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(),那就又回到原地修改了。