javascript - 如何在不改变原始对象的情况下创建对象的深度冻结版本?
问题描述
假设我们有以下对象:
"use strict"; // To trigger errors on frozen objects mutation attempts
const myObj = {
rootProp1: {
leafProp1: "hello",
leafProp2: "world",
rootProp2: "!",
};
当使用“经典”Object.freeze
方法时,我们只冻结对象的根属性:
const frozen = Object.freeze(myObj);
frozen.rootProp2 = "?"; // error --> OK
delete frozen.rootProp1; // error --> OK
frozen.extraRootProp = "how are you?"; // error --> OK
frozen.rootProp1.leafProp1 = "hi"; // NO ERROR --> I don't want this
为了深度冻结对象,我们可以使用这样的方法:
const deepFrozen = deepFreeze(myObj);
deepFrozen.rootProp1.leafProp1 = "hi"; // error --> OK
myObj.rootProp2 = "?"; // ERROR --> I don't want this
但这对我来说仍然是一个问题:我想要一个可以返回对象的冻结版本而不冻结原始对象的函数(我正在尝试学习函数式编程,所以我想要尽可能少的突变)。怎么做?
解决方案
在 ECMAScript 2018 (ES9) 中,感谢扩展运算符,可以使用这个简单的函数:
const deepFreeze = (obj) => typeof obj === "object"
? Object.freeze({
...Object.entries(obj).reduce(
(prev, [key, value]) => ({
...prev,
[key]: value ? deepFreeze(value) : value,
}),
{}
),
})
: typeof obj === "function" ? Object.freeze(obj) : obj;
推荐阅读
- javascript - 我如何将我的“输出”放入一种类型的表中,例如我所包含的表?
- ca - MKcert - 错误:添加证书:添加证书失败:访问被拒绝
- java - 在 Spring Batch 中使用 StaxEventItemWriter 时,ZipFileInputStream 读取方法正在延迟编组过程
- node.js - 如何将行索引作为值 Exceljs
- python - Folium 的 TimesliderChoropleth 上没有颜色
- excel - 用于日程比较的 Excel 高级 vlookups
- spring-boot - spring.config.additional-location 不会覆盖默认的 application.properties
- windows - 捕获 url 及其正文应使用 FWPM_LAYER_STREAM_V4
- fullcalendar - 在全日历中,如何从列表视图中排除事件源?
- laravel - Laravel Vue3 - 将令牌和用户信息传递到 Vue 商店