Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep an array with objects immutable in javascript?

I want to make an array based on two arrays - "ideaList" and "endorsements" declared globally. As ideaList and endorsements are used in other parts of the program I need them to be immutable, and I thought that .map and .filter would keep this immutability.

function prepareIdeaArray(){
var preFilteredIdeas=ideaList
        .filter(hasIdeaPassedControl)
        .map(obj => {obj.count = endorsements
                                 .filter(x=>x.ideaNumber===obj.ideaNumber)
                                 .reduce((sum, x)=>sum+x.count,0); 
                     obj.like = endorsements
                                 .filter(x=>x.ideaNumber===obj.ideaNumber && x.who===activeUser)
                                 .reduce((sum, x)=>sum+x.count,0)===0?false:true
                     obj.position = generatePosition(obj.status)
                     obj.description = obj.description.replace(/\n/g, '<br>')  
                     return obj;});
preFilteredIdeas.sort(compareOn.bind(null,'count',false)).sort(compareOn.bind(null,'position',true))
return preFilteredIdeas;
}

However, when I console.log ideaList after this function has been executed, I remark that objects of the array all have the "count", "like", "position" properties with values, which proves that the array has been mutated.

I tried by using .map only, but same result.

Would you know how I could prevent ideaList to get mutated? Also I would like to avoid to use const, as I declare ideaList globally first, and then assign to it some data in another function.

like image 209
Pierre Avatar asked Mar 25 '19 08:03

Pierre


People also ask

Are arrays immutable JavaScript?

In JavaScript, only objects and arrays are mutable, not primitive values.

How can we make an object immutable in JavaScript?

You can freeze (make immutable) an object using the function Object. freeze(obj) . The object passed to the freeze method will become immutable. The freeze() method also returns the same object.

Are objects immutable in JavaScript?

In JavaScript Arrays and Objects are not immutable. Their values can be changed over time. Both are always passed as a reference and the vast majority of available methods mutate data in place.

Is spread Operator immutable?

The original array remains intact if you copy the array with the spread operator and append it to the new one. Doing so supports immutability and prevents unforeseen side-effects.


1 Answers

You're not mutating the array itself but rather the objects that the array contains references to. .map() creates a copy of the array but the references contained in it points to the exact same objects as the original, which you've mutated by adding properties directly to them.

You need to make copies of these objects too and add the properties to these copies. A neat way to do this is to use object spread in .map() callback:

    .map(({ ...obj }) => {
      obj.count = endorsements
                             .filter(x=>x.ideaNumber===obj.ideaNumber)
      ...

If your environment doesn't support object spread syntax, clone the object with Object.assign():

    .map(originalObj => {
      const obj = Object.assign({}, originalObj);
      obj.count = endorsements
                             .filter(x=>x.ideaNumber===obj.ideaNumber)
      ...
like image 171
Lennholm Avatar answered Oct 15 '22 04:10

Lennholm