DEV Community

Discussion on: What the benefit immutable on the state management?

Collapse
 
daniel13rady profile image
Daniel Brady • Edited

Hmm, I think your example here might be misleading. If you remove the array mutation from both of your examples, you get the same results:

const oldState = ["apple", "banana", "orange"];

// mutable
/* oldState[0] = "tomato"; */
const newState = oldState;
oldState === newState; // true 

// or immutable
const updatedState = [...oldState];
/* updatedState[0] = "tomato"; */
const newState = updatedState;
oldState === newState; // false

The strict equality comparator, ===, does a simple pointer comparison when working with objects and arrays (or "object identity" comparison, if you prefer).

In the 'mutable' example, oldState === newState is true because they reference the same object: newState points to oldState, which points to an array. Array equality, as I think you allude to, does not look at contents.

In the 'immutable' example, oldState === newState is false because they are not the same object: you've made a copy, so newState points to an array and oldState points to a different array. Again, the equality comparison doesn't care about the contents, only the pointer.

With this in mind, Jannik, does your statement about the performance impact still hold true?

At least on the surface, it seems like the approach you've labeled "immutable" here would be less performant because you're copying the original array instead of reusing it. πŸ€” But I'm honestly not familiar with JS performance traits, curious of your thoughts.

Collapse
 
jannikwempe profile image
Jannik Wempe • Edited

In my opinion you added the missing explanation to my comment πŸ˜‰

The first one is mutable because objects (same with arrays and functions) are reference types and therefore changing one variable will also change the other (both pointing to the same object).

You are right, the copying itself is slower than just pointing to the same object. But to compare the oldState and the newState in the "mutable-way" you would have to compare all the values in the object/array and that can be much slower than the copying (just imagine a deeply nested object, eg. cart.products.apple.prices.eur).

Maybe in this example the copying could be slower than the comparison of the values due to the small array.

EDIT:
Just did a quick comparison in performance:

let oldState = ["apple", "banana", "orange"];
let newState;

let DOMHasToUpdate = false; // has to update if old and new state are different
console.time("mutable");
for (let i=0;i<1000000;i++) {
    newState = oldState;
    DOMHasToUpdate = oldState.map((el, idx) => el === newState[idx]).includes(false);
}
console.timeEnd("mutable");

console.time("immutable");
for (let i=0;i<1000000;i++) {
    newState = [...oldState];
    DOMHasToUpdate = !newState === oldState;
}
console.timeEnd("immutable");

// OUTPUT:
// mutable: 39.876953125ms
// immutable: 21.088134765625ms

I know here is no actual change in the state and changing the newState in the mutable way would also lead to an update of the oldState but it is more about the performance for copying vs. comparing values.

But yes, I think my point regarding performance still holds true.

Thread Thread
 
malloc007 profile image
Ryota Murakami

Thank you for your meaningful input with @dabrady 😎
I imagined rough mind model about last perfomance comparison mutable like "full-scan", immutable like "check book cover".

That is not correct strictly, but I got a chance re-learning around JavaScript's Logical Comparison! 🀩🍺

Thread Thread
 
daniel13rady profile image
Daniel Brady

I imagined rough mind model about last perfomance comparison mutable like "full-scan", immutable like "check book cover".

That's a really nice mental model 😍