登录
首页 >  文章 >  前端

Array.prototype.with使用详解与示例

时间:2026-05-27 16:54:49 249浏览 收藏

Array.prototype.with 是 ES2023 引入的现代化、不可变数组方法,专为安全、高效地替换指定索引处的单个元素而生——它不修改原数组,仅接受数字索引和新值两个参数,语义清晰、性能优越(V8 已深度优化),且对稀疏数组和代理数组更友好;但需注意其严格索引校验(负数或越界即抛 RangeError)、不支持条件查找或批量操作等限制,适用于现代浏览器和 Node.js 环境,是替代繁琐 slice + spread 模式、提升代码可读性与健壮性的理想选择。

如何用 Array.prototype.with 在不修改原数组时替换特定索引的元素

Array.prototype.with 是什么,它能直接替换索引元素吗

Array.prototype.with 是 ES2023 新增的不可变数组方法,专为「安全替换单个索引值」设计。它不修改原数组,而是返回一个新数组,且只在指定索引位置更新值,其余元素完全保持引用不变(浅拷贝)。

它不是通用“查找并替换”,也不支持条件匹配或多个索引——只接受两个参数:indexvalue。越界索引会抛出 RangeError,这点和 at() 不同。

常见错误现象:用负数索引(如 -1)直接调用,结果报错;或误以为它支持对象键名查找,实际只认数字索引。

怎么正确使用 with 替换第 2 个元素(索引 1)

确保索引合法(非负整数、小于数组长度),传入新值即可:

const arr = ['a', 'b', 'c'];
const newArr = arr.with(1, 'x');
console.log(newArr); // ['a', 'x', 'c']
console.log(arr);    // ['a', 'b', 'c'] ← 原数组未变
  • 索引必须是整数,1.0Math.floor(1) 都可以,但 '1' 会隐式转为数字,不推荐依赖类型转换
  • 如果索引等于 arr.length,会扩展数组(类似 push),但仅限于末尾追加一个元素
  • 索引为 arr.length + 1 或更大时,直接抛出 RangeError: Invalid index

和 slice + spread 的写法比,with 有什么优势

传统写法:[...arr.slice(0, i), newValue, ...arr.slice(i + 1)] 可读性差、创建多个中间数组、性能略低。

with 更简洁、语义明确,且引擎可做优化(V8 已对 with 做了专门的快速路径):

  • 避免重复切片,内存分配更少
  • 对稀疏数组行为更一致(slice 会丢弃空槽,with 保留)
  • 不触发 getter/setter(如果数组被代理,slice 可能意外触发副作用,with 更纯净)

但注意:目前 Safari 16.4+、Chrome 111+、Firefox 114+ 支持,Node.js 20.1+ 启用 —— 旧环境需 polyfill 或降级。

容易忽略的边界情况:替换最后一个元素、空数组、索引 0

这些场景看似简单,但容易踩坑:

  • 替换最后一个元素:用 arr.with(arr.length - 1, newVal),别手快写成 arr.length(那会追加)
  • 空数组调用 [].with(0, 'x') → 报错,因为 0 >= [].length(即 0 >= 0)不成立,实际要求 index ,所以空数组无法用 with 插入首个元素
  • 索引 0 是完全合法的:['a','b'].with(0, 'z') 返回 ['z','b'],无特殊处理
  • 如果数组有 Symbol.isConcatSpreadable: false 等自定义属性,with 仍能正常工作,而 spread 写法可能失效

真正要注意的是:它只解决「已知索引」的单点替换。如果你要根据值找索引再替换,得先用 indexOffindIndex,再把结果传给 with —— 这两步不能合并,也没有内置 shortcut。

理论要掌握,实操不能落!以上关于《Array.prototype.with使用详解与示例》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>