-2

I have a factory function that returns an object with one function. Now the question is I want to update the value property on this object without mutating the object, I want in particular to return a new object that has all the functions and with the updated property Here is what I have tried

 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
Fadi
  • 135
  • 2
  • 10
  • The object your `temperature` function returns is just a plain object. They don't have a `map` function (the only one provided by the standard JavaScript library is the one on arrays). Also note that there's no point to `Object.assign({/*...*.})` (e.g., with just a single argument), just use `{/*...*/}`. `Object.assign` is only useful with more than one argument. The code is also just generally overcomplex for the purpose that it seems to be meant for... – T.J. Crowder Oct 11 '20 at 10:50
  • 1
    thanks for the info about object.assign, you are quite right on this. and the complexity is actually the problem in this code, and I could not make it simpler. the question is basically how can I achieve the desired functionality I want in a simple way – Fadi Oct 11 '20 at 10:59

2 Answers2

2

Some issues:

  • The convertToC method is not well defined. You execute the call to temperature() immediately instead of defining a function that calls it.

  • The convertToC method also wrongly uses the destructuring spread syntax on a non-array (hence the error): ({ ...args }). Moreover it is not clear where the idea of calling .map comes from, as it applies to arrays, not objects.

    For dealing with this and the previous issue, change that definition to:

    const convertToC = () => temperature(Celsiusconverter(args));
    
  • In the next line you call Object.assign with one argument: that is a null-operation. You intended to extend the args object, but instead you defined a property called args with args as nested object value. Here you could use the spread syntax:

    return {
        ...args,
        convertToC, 
        getValue,
        getUnit
    };
    
  • In the Celsiusconverter you make a similar mistake: you return an object with an args property. You should just return args (which is already a shallow copy of the function argument):

    return args;
    
  • In the main program you should not have to pass temperatureObject to the convertToC method, since the object on which you call it, already knows about that temperatureObject. It should be called as:

    const temp2 = temp.convertToC();
    

So taking all that together you get:

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());
trincot
  • 211,288
  • 25
  • 175
  • 211
  • 1
    Not sure why the OP accepted this answer, TBH. The OP specifies in the question that there should be no mutation, and that is in fact the main driver for the complexity in their code. This answer fails that requirement, yet is accepted by the OP. – Jörg W Mittag Oct 11 '20 at 16:21
  • @JörgWMittag, if you refer to `newArgs`, then that is just a temporary variable that the OP already initialised like that. It is of course no issue to replace that with an object literal having `value` and `unit`. Is it that what you refer to? – trincot Oct 11 '20 at 16:24
  • 1
    Care to comment on what you refer to, @JörgWMittag? Both functions return newly created objects. They don't mutate the objects they get as argument. – trincot Oct 11 '20 at 16:30
  • 2
    @JörgWMittag the answer satisfies the mutability requirement in the question that is why it has been accepted. the complexity is driven by the requirement about the immutability. which part of the answer you are referring to? so we all can be more clever by understanding you point of view. thanks – Fadi Oct 13 '20 at 08:19
  • OP subject asks how to make an object immutable. OP body asks how to update an object without mutating. These are entirely different questions. @trincot answered the latter, while Jörg is pointing out it does not answer the former. – user1713450 Oct 16 '20 at 06:29
-1

Not sure the JavaScript object has a map function like you're attempting ({ ...args }).map((x)=> Celsiusconverter(x)).

Here's a StackOverflow post explaining the same: map function for objects (instead of arrays)

I tried by changing the JavaScript object to an array (as suggested in the StackOverflow post) and that results in a stack overflow error (pun intended).