使用 Array.prototype.with 更新不可变数组

庆祝:此功能现已在所有三个主要浏览器引擎中可用!

浏览器最近获得了一种新的可互操作方法,您可以在数组上调用它:Array.prototype.with()

Browser Support 浏览器支持:

  • chrome 110
  • Edge 110
  • firefox 115
  • Safari 16

本文探讨了此方法的工作原理以及如何使用它来更新数组而不改变原始数组。

Array.prototype.with(index, value) 简介

Array.prototype.with(index, value) 方法返回所调用的数组的副本,并将 index 设置为您提供的新 value

以下示例显示年龄数组。您想要创建数组的新副本,同时将第二个年龄从 15 更改为 16:

js 复制代码
const ages = [10, 15, 20, 25];

const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

分解代码: ages.with(...) 返回 ages 变量的副本,而不修改原始数组。 ages.with(1, ...) 替换第二项 ( index = 1 )ages.with(1, 16) 将第二个项目分配给 16

这就是你如何通过修改来创建一个新的数组副本。

当您想要确保原始数组保持不变时,这非常有用,本文介绍了这方面的一些用例。但是,现在看看如果使用括号表示法会发生什么:

js 复制代码
const ages = [10, 15, 20, 25];

const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)

正如您所看到的,在此示例中还修改了 ages 变量。这是因为当您分配 ages = newAges 时,JavaScript 不会复制该数组,而是创建对另一个数组的引用。因此,其中一个的任何更改也会影响另一个,因为它们都指向同一个数组。

Array.prototype.with() 和不变性

不变性是许多前端库和框架的核心,仅举几例:React(和 redux)和 Vue

此外,其他库和框架不一定需要不变性,但鼓励它以获得更好的性能:Angular 和 Lit

因此,开发人员经常不得不使用其他返回数组副本的方法,从而牺牲了代码的可读性:

js 复制代码
const ages = [10, 15, 20, 25];

const newAges = ages.map((age, index) => {
    if (index === 1) {
         return 16;
    }
    return age;
});

console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)

下面是一个 Codepen 示例,说明了如何在 React 中结合 useState 使用 .with() 来永久更新项目数组:

js 复制代码
import React, {useState} from 'https://esm.sh/react@18.2.0'
import ReactDOM from 'https://esm.sh/react-dom@18.2.0'


function App() {
    const [items, setItems] = useState(["Item 1", "Item 2", "Item 3"]);

    const updateItem = (index) => {
        // Immutable update
        setItems(items.with(index, `Updated item ${index + 1}`));
    };

    return (
        <ul>
            {items.map((item, index) => (
                <li key={index} className="item">
                    <button onClick={() => updateItem(index)}>Update</button>
                    <span>{item}</span>
                </li>
            ))}
        </ul>
    );
}

ReactDOM.render(<App />,
document.getElementById("root"))

由于 .with() 方法返回数组的副本,因此您可以链接多个 .with() 调用甚至其他数组方法。以下示例演示了从数组中递增第二个和第三个年龄:

js 复制代码
const ages = [10, 15, 20, 25];

const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)

console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

其他新的不可变方法

其他三种方法最近也实现了互操作:

  • Array.prototype.toReversed() 反转数组而不改变原始数组。
  • Array.prototype.toSorted() 对数组进行排序而不改变原始数组。
  • Array.prototype.toSpliced() 其工作方式类似于 .splice() 但不会改变原始数组。

根据 MDN 的说法,这三种方法是其对应方法的复制版本。这些方法也可以用在期望或首选不变性的地方。

总之,使用本文介绍的四种方法之一可以在 JavaScript 中更轻松地实现不可变更新。具体来说, .with() 方法可以更轻松地更新数组的单个元素,而无需更改原始数组。


web.developers.google.cn/blog/array-...

相关推荐
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅10 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅11 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊11 小时前
jwt介绍
前端
爱敲代码的小鱼11 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax