问题描述
假设我们有以下对象:
"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;