如何在不更改原始对象的情况下创建对象的深度冻结版本?

问题描述

假设我们有以下对象:

"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

为了深深冻结对象,我们可以使用类似this one的方法:

const deepFrozen = deepFreeze(myObj);

deepFrozen.rootProp1.leafProp1 = "hi"; // error --> OK
myObj.rootProp2 = "?"; // ERROR --> I don't want this

但这对我来说仍然是一个问题:我想要一个可以返回对象的冻结版本的函数,而不冻结原始对象(我正在尝试学习函数式编程,所以我想尽可能少的突变)。该怎么做?

解决方法

在ECMAScript 2018(ES9)中,借助spread operator,可以使用以下简单功能:

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;

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...