javascript数组变异方法共7个:push、pop、shift、unshift、splice、sort、reverse,均直接修改原数组;不可变方法如map、filter、tosorted等返回新数组,不改变原数组,更适配react/vue响应式机制与函数式编程。

JavaScript 数组操作中,“不可变”和“变异”(即可变)的本质区别在于:是否直接修改原数组。不可变方法返回新数组,原数组保持不变;变异方法则就地修改原数组,返回值可能是新长度、被删元素或原数组本身。这个差异直接影响状态管理、调试体验和框架行为,尤其在 React、Vue 等响应式环境中尤为关键。
哪些方法会改变原数组?
这些是典型的变异方法,执行后原数组内容立即变化:
- push()、pop()、shift()、unshift():增删首尾元素
- reverse()、sort():重排数组顺序
- splice():删除、替换或插入元素(功能最强,也最易误用)
例如:const arr = [2, 1]; arr.sort(); 后,arr 变成 [1, 2] —— 原引用指向的内存已被改写。
哪些方法不改变原数组?
这些方法返回新数组或新值,原数组完全不受影响:
- filter()、map()、flatMap():生成新数组
- slice()、concat()、toSorted()、toReversed()、toSpliced()、with():返回副本或变换后的新数组
- find()、findIndex()、includes()、indexOf():只读查询,返回值非数组
比如:const arr = [3, 1]; const sorted = arr.toSorted(); 后,arr 仍是 [3, 1],sorted 是新数组 [1, 3]。
浅拷贝不是深拷贝,这点必须分清
像 slice()、[...arr]、Array.from(arr) 这些“不改变原数组”的方法,只做浅拷贝 —— 它们对嵌套对象或子数组仍共享引用。
例如:const arr = [{ name: 'Alice' }]; const copy = arr.slice(); copy[0].name = 'Bob'; 会导致 arr[0].name 也变成 'Bob'。
若需彻底隔离,且结构含对象或数组,应使用 structuredClone()(现代环境)或 Lodash 的 _.cloneDeep()(兼容旧版)。
为什么不可变更受现代开发青睐?
不可变操作让数据变更可预测、可追溯,特别适合以下场景:
- React 中的 state 更新:直接修改数组不会触发重新渲染,而赋值新数组能被严格比较识别
- 时间旅行调试(如 Redux DevTools):历史快照必须独立,否则回溯时数据已污染
- 多线程/Worker 场景:避免共享内存引发竞态条件
- 函数式编程风格:强调纯函数与无副作用,提升测试与重构效率
新标准方法(如 toSorted)正是为填补过去缺失的“安全不可变替代品”而设计,减少开发者手动写 [...arr].sort() 的冗余。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











