array.prototype.tospliced() 是 es2023 引入的不可变数组方法,返回新数组,语义清晰、安全高效,适用于 redux/vuex 等需要不可变更新的场景,现代环境原生支持,babel 可降级。

Array.prototype.toSpliced() 是 ES2023 引入的原生数组方法,它不修改原数组,而是返回一个新数组,完美契合 Redux/Vuex 所需的不可变更新原则。相比 splice()(会直接修改原数组),toSpliced() 更安全、更语义清晰,也更易读写。
为什么 toSpliced() 比 slice + splice 组合更合适?
传统纯函数式数组更新常靠 [...arr.slice(0, start), ...newItems, ...arr.slice(end)] 实现,但逻辑分散、易出错,尤其处理删除+插入混合操作时。而 toSpliced(start, deleteCount, ...items) 一步到位:
- 语义明确:从哪删、删几个、插什么,一目了然
- 零副作用:严格返回新数组,无需担心引用污染
- 边界安全:自动处理负索引、越界 deleteCount(如超出长度则删到末尾)
- 兼容性好:现代浏览器和 Node.js 18.17+ / 20.6+ 原生支持,Babel 可通过
@babel/preset-env自动降级(需启用shippedProposals: true)
在 Redux Toolkit 中更新数组状态
RTK 的 createSlice 鼓励直接“写”状态(借助 Immer),但显式使用 toSpliced() 更透明、更可控,适合复杂逻辑或团队规范要求显式不可变操作的场景:
import { createSlice } from '@reduxjs/toolkit';
<p>const listSlice = createSlice({
name: 'list',
initialState: ['a', 'b', 'c'],
reducers: {
insertAt: (state, action) => {
const { index, item } = action.payload;
// ✅ 纯函数式:返回新数组,不改 state
return state.toSpliced(index, 0, item);
},
removeAt: (state, action) => {
const { index } = action.payload;
return state.toSpliced(index, 1);
},
replaceRange: (state, action) => {
const { from, to, items } = action.payload;
const deleteCount = Math.max(0, to - from);
return state.toSpliced(from, deleteCount, ...items);
}
}
});</p>
在 Vuex 4(Composition API)中响应式更新
Vuex 4 支持组合式用法,配合 ref 或 reactive 管理状态。由于 Vue 的响应式系统依赖对象/数组的属性访问,直接赋值新数组即可触发更新:
import { defineStore } from 'pinia'; // 推荐 Pinia;若坚持 Vuex 4,逻辑类似
<p>export const useListStore = defineStore('list', {
state: () => ({
items: ['x', 'y', 'z'] as string[]
}),
actions: {
insertFirst(item: string) {
this.items = this.items.toSpliced(0, 0, item); // ✅ 触发响应式更新
},
swap(firstIdx: number, secondIdx: number) {
const arr = [...this.items];
const a = arr[firstIdx];
const b = arr[secondIdx];
arr[firstIdx] = b;
arr[secondIdx] = a;
this.items = arr; // 此处仍需整体赋值,但 toSpliced 可简化部分逻辑
}
}
});</p>
注意:Vuex 本身不拦截数组方法调用,所以不能像 push 那样直接调用 toSpliced —— 必须显式赋值给 state 字段,才能被响应式系统捕获。
与 immer 或其他不可变工具对比
toSpliced() 不依赖第三方库,轻量、标准、可预测。但它只解决数组切片类更新;对于嵌套对象更新、Map/Set 操作等,仍需结合 structuredClone、immer 或手写递归拷贝。建议:
- 简单数组增删改 → 直接用
toSpliced() - 深层嵌套结构 → 用 Immer(
produce)保持代码简洁 - 需要兼容老环境且不想引入 Babel → 回退为
slice+concat模式,或封装一个 polyfill
不复杂但容易忽略:确保你的构建工具已启用 ES2023 支持,TypeScript 用户需将 lib 设为 ["ES2023"] 或更高,并安装最新 @types/node。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











