使用 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-...

相关推荐
前端拾光者14 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
Json_1817901448032 分钟前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing1 小时前
React核心功能详解(一)
前端·react.js·前端框架
捂月1 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
深度混淆1 小时前
实用功能,觊觎(Edge)浏览器的内置截(长)图功能
前端·edge
Smartdaili China1 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
秦老师Q1 小时前
「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用
前端·chrome·edge
滴水可藏海1 小时前
Chrome离线安装包下载
前端·chrome