slice方法不会修改原数组,它只读取、复制并返回新数组;支持负索引和区间截取,但仅浅拷贝,嵌套对象仍共享引用。

slice 方法本身就不会修改原数组
这是最常被误解的一点:slice() 是纯函数式操作,它只读取、复制、返回新数组,绝不会碰原数组的 length 或任何元素。如果你发现原数组“变了”,那一定是后续代码里用了 splice()、sort()、reverse() 或直接赋值(比如 arr[0] = ...)导致的。
正确调用 slice 的参数组合
slice() 接收两个可选参数:start 和 end,都是索引位置(含头不含尾)。常见用法包括:
-
arr.slice()→ 浅拷贝整个数组 -
arr.slice(2)→ 从索引 2 开始到末尾 -
arr.slice(1, 4)→ 取索引 1、2、3 的三个元素 -
arr.slice(-2)→ 取最后两个元素(负数从末尾计数) -
arr.slice(0, -1)→ 去掉最后一个元素(常用于“非破坏性弹出”)
注意浅拷贝陷阱:嵌套对象仍共享引用
slice() 只做一层浅拷贝。如果原数组里有对象、数组或函数,新数组里存的是同一份引用——改新数组里的对象属性,原数组也会“看到”变化。
const arr = [{ name: 'a' }, { name: 'b' }];
const newArr = arr.slice();
newArr[0].name = 'x';
console.log(arr[0].name); // 'x' —— 原数组也被改了
需要深拷贝时,不能只靠 slice(),得配合 JSON.parse(JSON.stringify())(仅限纯数据)、structuredClone()(现代环境),或专用库如 lodash 的 cloneDeep()。
替代方案对比:为什么不用扩展运算符?
用 [...arr] 或 Array.from(arr) 也能实现不修改原数组的拷贝,但和 slice() 有细微差别:
-
slice()支持负索引和区间截取,[...arr]只能全量展开 -
slice()在稀疏数组上保留空位([1,,3].slice()还是稀疏的),而扩展运算符会把空位转为undefined - 性能上三者差异极小,日常无需纠结;但若需精确控制截取范围,
slice()更直接
真正容易被忽略的是:很多人在链式调用中误以为 filter() 或 map() 会改变原数组——其实它们也不会,但新手常把 slice() 和这些方法混为一谈,结果反复检查 slice() 却没发现真正的问题出在别处。










