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

更新日期: 2024-03-18阅读: 695标签: 数组

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

浏览器最近获得了一种新的可互操作方法,您可以在数组上调用它: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:

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 。

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

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

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

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

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() 来永久更新项目数组:

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() 调用甚至其他数组方法。以下示例演示了从数组中递增第二个和第三个年龄:

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() 方法可以更轻松地更新数组的单个元素,而无需更改原始数组。

作者:杭州程序员张张,来自:https://segmentfault.com/a/1190000044702790

链接: https://fly63.com/article/detial/12686

探索JavaScript数组奥秘

avaScript数组同后端语言一样,具有它自己的数据结构,归根结底,这种数据结构,本质就是一种集合。在后端语言中(如java,.net等),数组是这样定义的:数组是用来存储相同数据类型的集合

js使用数组+循环+条件实现数字转换为汉字的简单方法。

单个数字转汉字的解决方法:利用数组存储0-9的汉字、 ary.length和str.length不用多说,这是指ary数组和str字符串的长度。这里我们需要注意的是str.charAt(j)和ary[i],分别指在str这个字符串中索引为j的元素,在ary中索引为i的元素。

[译]async-await 数组循环的几个坑

在 Javascript 循环中使用 async/ await 循环遍历数组似乎很简单,但是在将两者结合使用时需要注意一些非直观的行为。让我们看看三个不同的例子,看看你应该注意什么,以及哪个循环最适合特定用例。

数组、字符串去重

今天说的数组和字符串去重呢,主要用到es6新的数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值,所以活用Set来进行数组和字符串的去重。

JavaScript 数组方法

数组方法:1、Array.join([param]) 方法:将数组中所有的元素都转换为字符串并连接起来,通过字符 param 连接,默认使用逗号,返回最后生成的字符串2、Array.reverse() 方法:将数组中的元素颠倒顺序(在原数组中重新排列它们),返回逆序数组

如何删除JavaScript 数组中的虚值

falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值.JavaScript 在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion )将值转换为布尔值,比如:在条件语句或者循环语句中。

JavaScript中十种一步拷贝数组的方法

JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下。扩展运算符(浅拷贝)自从ES6出现以来,这已经成为最流行的方法。

JS数组的几个经典api

本文主要来讲数组api的一些操作,如简单实现扁平化n维数组、数组去重、求数组最大值、数组求和、排序、对象和数组的转化等。扁平化嵌套数组/展平和阵列孔——flat()

关于Vue不能监听(watch)数组变化

vue无法监听数组变化的情况,但是数组在下面两种情况下无法监听:利用索引直接设置数组项时,例如arr[indexofitem]=newValue;修改数组的长度时,例如arr.length=newLength

JS计算两个数组的交集、差集、并集、补集(多种实现方式)

使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本,使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本。也不用引入其他第三方库。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!