如何在 Javascript 中使对象不可变

how to make object immutable in Javascript

我有一个工厂函数,return是一个只有一个函数的对象。现在的问题是我想更新这个对象的值 属性 而不改变对象,我特别想要 return 一个具有所有功能和更新的 属性 的新对象 这是我试过的

 function temperature(args) {
  
    const convertToC = temperature(({ ...args }).map((x)=> Celsiusconverter(x)))//this does not work
    return Object.assign({
        args,
        convertToC
    })
}

    function Celsiusconverter(args) {
       const newArgs = {...args}
       newArgs.value = (newArgs.value - 32) * (5 / 9)
       newArgs.unit = 'C'
       return {
           newArgs
        }
    }

 
    const temeratureObject = {
        unit: 'C',
        value: 10,
    }

    const temp = temperature(temeratureObject)
    const temp2  = temp.convertToC(temeratureObject);
    console.log(temp2.getValue()) // this gives me this error:  TypeError: {(intermediate value)}.map is not a function

不确定 JavaScript 对象是否具有您正在尝试的地图功能 ({ ...args }).map((x)=> Celsiusconverter(x))

这是 Whosebug post 的解释: map function for objects (instead of arrays)

我尝试将 JavaScript 对象更改为数组(如 Whosebug post 中所建议),这会导致堆栈溢出错误(双关语)。

一些问题:

  • convertToC 方法没有明确定义。您立即 执行 temperature() 的调用,而不是定义调用它的函数。

  • convertToC 方法还错误地在 non-array 上使用解构扩展语法(因此出现错误):({ ...args })。此外,不清楚调用 .map 的想法从何而来,因为它适用于数组,而不是对象。

    为了处理这个问题和上一个问题,将该定义更改为:

    const convertToC = () => temperature(Celsiusconverter(args));
    
  • 在下一行中,您使用一个参数调用 Object.assign:即 null-operation。您打算 扩展 args 对象,但您定义了一个名为 args 的 属性,其中 args 作为嵌套对象值。这里你可以使用传播语法:

    return {
        ...args,
        convertToC, 
        getValue,
        getUnit
    };
    
  • Celsiusconverter 中你犯了类似的错误:你 return 一个带有 args 属性 的对象。你应该只是 return args (这已经是函数参数的浅拷贝):

    return args;
    
  • 在主程序中,您不必将 temperatureObject 传递给 convertToC 方法,因为调用它的对象已经知道 temperatureObject.它应该被称为:

    const temp2 = temp.convertToC();
    

所以把所有这些放在一起你会得到:

function temperature(args) {
    const getValue = () => args.value;
    const getUnit = () => args.unit;
    const convertToC = () => temperature(Celsiusconverter(args));
    return {
        ...args,
        convertToC, 
        getValue,
        getUnit
    };
}

function Celsiusconverter(args) {
   const newArgs = {...args};
   newArgs.value = (newArgs.value - 32) * (5 / 9);
   newArgs.unit = 'C';
   return newArgs;
}


const temperatureObject = {
    unit: 'C',
    value: 10,
}

const temp = temperature(temperatureObject);
const temp2 = temp.convertToC();
console.log(temp2.getValue());