Array.prototype.with是ES2023新增的不可变数组方法,专为安全替换指定索引元素设计;它不修改原数组,仅接受整数索引和新值两个参数,越界或非法索引会抛出RangeError。

Array.prototype.with 是什么,它能直接替换索引元素吗
Array.prototype.with 是 ECMAScript 2023(ES14)新增的方法,专为「不可变地替换指定索引处的元素」设计。它不修改原数组,而是返回一个新数组,且只在目标索引位置替换成新值,其余元素完全保留 —— 这正是你想要的语义。
注意:它不是“通用更新工具”,不能传入回调函数或条件判断;它只接受两个参数:index 和 value,且 index 必须是有效整数(支持负索引,如 -1 表示末尾)。
怎么用 with 替换第 2 个元素(索引为 1)
假设你想把 [10, 20, 30] 中索引 1 处的 20 换成 99:
const arr = [10, 20, 30]; const newArr = arr.with(1, 99); // newArr → [10, 99, 30] // arr 保持不变 → [10, 20, 30]
常见误用点:
- 传入非数字索引(如
"1"或null)会触发RangeError: Invalid array index - 索引越界(如
arr.with(5, 'x')在长度为 3 的数组上)也会报同样的RangeError,它不自动扩容 - 负索引从末尾计数:
[1,2,3].with(-1, 9)→[1,2,9],但[1,2,3].with(-4, 9)仍越界
with 与 slice + splice + concat 等旧写法对比
过去常用 [...arr.slice(0, i), newValue, ...arr.slice(i + 1)] 实现类似效果,但 with 更简洁、语义更明确、性能也略优(V8 等引擎已对其做底层优化)。
关键差异:
-
with不创建中间数组片段,也不涉及展开运算符的内存分配开销 -
with对稀疏数组行为更可靠(旧方法可能意外填充undefined) - 不支持 IE、Node.js
容易被忽略的边界情况
with 对 NaN、undefined、0、-0 等值完全按字面量替换,无特殊转换。但它对 length 属性无影响 —— 即使你用 with 替换最后一个元素,新数组 length 仍等于原数组。
真正容易出错的是索引合法性校验逻辑:它要求 index 满足 index >= -this.length && index (即数学意义上的有效位置),而不是简单 <code>index in arr。这意味着空数组 [] 上任何 with 调用都会失败 —— 包括 [].with(0, 'x') 和 [].with(-1, 'x')。

















