在 JavaScript 中保持对象和数组不可变的最佳实践。不变性

2025-06-04

在 JavaScript 中保持对象和数组不可变的最佳实践。

不变性

不变性

不变性是函数式编程的核心原则。在本文中,我将列出一些在 JavaScript 中不使用任何第三方库即可保持数据结构不变的最佳实践。

那么 Javascript 中哪些数据类型是不可变的?

字符串、数字和布尔值等原始数据类型默认是不可变的,它们无法被修改,所以你不需要使用任何“魔法”来保持它们的不可变性。但对于默认可变的对象和数组,我们不能说它们也是如此,因为它们只是引用。
接下来,我们将介绍一些有助于我们保持对象和数组不可变的操作。

对数组的操作。

克隆原始数据类型的数组。

const sourceArray = [1,2,3];
const clonedArray = [...sourceArray];
// or you can do
const clonedArray = sourceArray.slice(0);
Enter fullscreen mode Exit fullscreen mode

克隆一个对象数组,其 props 是原始数据类型。

const sourceArray = [{ a: 1}, { b: 2 }, { c: 3}];
const clonedArray = sourceArray.map(item => ({...item}));
Enter fullscreen mode Exit fullscreen mode

向数组中添加新元素。

const sourceArray = [1,2,3];
const newArray = [...sourceArray, 4];
const sourceArray = [{ a: 1}, { b: 2 }, { c: 3}];
const newArray = [...sourceArray, { d: 4}];
Enter fullscreen mode Exit fullscreen mode

从数组中删除一个元素。

const itemToRemove = 3;
const sourceArray = [1,2,3];
const newArray = sourceArray.filter(item => item !== itemToRemove);
Enter fullscreen mode Exit fullscreen mode

将元素替换到数组中。

const itemToAdd = { id: 2, a: 4 };
const sourceArray = [{id: 1, a: 1}, {id: 2, a: 2}, {id: 3, a: 3}];

// replacing without caring about position
const newArray = [...sourceArray.filter(item => item.id !== itemToAdd.id), itemToAdd];

// replacing caring about position
const indexOldElement = sourceArray.findIndex(({ id }) => id == itemToAdd.id);
const newArray = Object.assign([...sourceArray], {[indexOldElement]: itemToAdd});

// or you can do
const newArray = [...sourceArray.slice(0, indexOldElement), itemToAdd, ...sourceArray.slice(indexOldElement + 1)]
Enter fullscreen mode Exit fullscreen mode

对对象的操作。

添加新道具。

const sourceObj = { a: 1, b: 2};
const newProp = { c: 3 };
const newObj = { ...sourceObj, ...newProp};
// or you can do
const c = 3;
const newObj = { ...sourceObj, c};
// newObj = { a: 1, b: 2, c: 3};
Enter fullscreen mode Exit fullscreen mode

 移除道具。

const sourceObj = { a: 1, b: 2, c: 3};
const { b, ...newObj } = sourceObj;
// console.log(newObj) => { a: 1, c: 3};
Enter fullscreen mode Exit fullscreen mode

更新一个嵌套对象,其 props 是原始的。

const sourceObj = { a: 1, b: 2, c: { d: 3, e :4 } };
const c = { ...sourceObj.c, f: 5 }
const newObj = { ...sourceObj, c };
Enter fullscreen mode Exit fullscreen mode

更新一个嵌套对象,其 props 不是原始的。

const sourceObj = { a: 1, b: 2, c: { d: [1, 2, 3 ], e :4 } };
const d = [ ...sourceObj.c.d, 4 ];
const c = { ...sourceObj.c, d }
const newObj = { ...sourceObj, c };
Enter fullscreen mode Exit fullscreen mode

不幸的是,正确地将不可变更新应用于嵌套对象的过程很容易变得冗长且难以阅读。

关于表演您能说几句话吗?

创建新对象在时间和内存消耗方面更加昂贵,但在很多情况下这些缺点小于优点。

在开始编码之前,您应该考虑一些优点,例如能够仅依靠身份/严格相等运算符检查来快速比较两个不可变对象oldObject === newObject,或者减少在不同组件之间共享数据结构的应用程序中可能发生的严重错误的可能性。

结论

如果您目前正在使用或学习任何基于不可变性的库,那么上述所有操作都可以为您提供帮助。希望您喜欢阅读这篇短文,欢迎提供反馈!

文章来源:https://dev.to/antonio_pangall/best-practices-to-keep-objects-and-arrays-immutable-in-javascript-3nmm
PREV
项目和项目管理的质量
NEXT
OAuth 新手入门技巧 身份验证与授权分离 短期令牌 刷新令牌 安全流程影响 未来展望