Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Immutability in JavaScript
Carlos Cuesta
Carlos Cuesta

Posted on • Originally published atcarloscuesta.me

     

Immutability in JavaScript

Have you ever heard something aboutimmutability? I'm mostly sure the answer isyes!, particularly on the programming ecosystem. Despite being a popular term, there are some misconceptions about the importance and principles of it. Let's dive in into it!

What does it mean?

Immutability is thestate of not changing, orbeing unable to be changed.

On a programming context, means that when we need tochange the state in our program, wemust create and track a new value rather than mutating the existing one.

🚨 This does not mean we can't have values that change over the lifecycle of our program. That's a common misconception about immutability 🖐

Immutable 🆚 Mutable

To understand the difference between both, take a look at the following example. Imagine that we have a shopping cart 🛒object, that contains two properties,id andtotal.

constshoppingCart={id:'69zd841',total:0}
Enter fullscreen modeExit fullscreen mode

Let's say that we want to update thetotal property of ourshoppingCart, how can we achieve this?

Clone and update

Using thespread operator we can create a new object cloning the previous cart and updating thetotal property, while preserving our original object in a pristine condition.

{...shoppingCart,total:15}
Enter fullscreen modeExit fullscreen mode
Mutate

Through theobject property accessor we can perform a modification to our original object.

cart.total=15
Enter fullscreen modeExit fullscreen mode

Thedifference between those two examples is that on the first one we preserved our original shopping cart and we created a new one and on the second one weoverwrited the value of thetotal property.

The benefits

Now that we understood the concept of immutability and the difference between mutable 🆚 immutable data, let's see the benefits of applying it.

Immutability is like a seatbelt, it won't prevent an accident but it saves your life when it does

Predictability

Predictable code is code where you cananticipate the outcome with a single read. Mutation hides change, as we've seen before, the source is lost. Hidden change creates unexpected side effects that can cause complex bugs 🐛.

When we can predict the outcome, we start to feel more confident with our code simplifying our thought process. This helps us reason easier about our program.

Tracking mutations

When you mutate data, you're overwriting the same reference every time that you update something as we've pointed on the first example. Then it's impossible to have a track of the changes you've done to the program state.

Immutable data gives you a clear history of state to the program, because you're creating a new reference based on the source.

The drawbacks

Whenever we start creating new values such asArray,Object etc, instead of mutating existing ones the next question always is is:What kind of impact has this for performance?.

Performance

Avoiding mutations has acost that's correct, every time we have to reallocate a new value, that's consumingCPU time andmemory, including thegarbage collection process for values that are no longer referenced.

Is that anacceptable trade-off?It depends. We need somecontext to answer that question, for example:

If you have a single state change, that happens a few times on the lifecycle of your program, creating a new object, is certainly not a problem. It won't have no practical impact on the performance of the app. Compared to the time you will save not having to track and fix bugs caused by side effects, the winner clearly is immutability 🎉

Again, if that state change is going to occur frequently, or it happens in a critical path of your app, then performance is a totally valid concern 👍

Thankfully, there are some libraries out there that will provide performance optimizations such asImmutable.js andseamless-immutable.

Immutable data in JS

Constants

A constant is avariable thatcannot be reassigned andredeclared. This is an important concept to understand, because it does not mean the value it holds is immutable.

The use ofconst tells the human being who's reading your code that the following variable won't be reassigned or redeclared. It's a great improvement incode readability because we're intentionally communicating that.

constfruits=['🍌','🍓','🥥']// We can't reassign the constant// ❌ TypeError: Assignment to constant variable.fruits=['🍏']// We can't redeclare the constant// ❌ SyntaxError: Identifier 'fruits' has already been declaredconstfruits=['🥝']// ✅ We can mutate the value as we want// fruits -> ['🍌','🍓', '🥥', '🍍']fruits.push('🍍')
Enter fullscreen modeExit fullscreen mode

Spread syntax

Also known as..., it's a useful operator for cloningiterables such asArray orObject.

constfruits=['🍌','🍓','🥥']constshoppingCart={id:'69zd841',total:0}// Add a some fruits to the end of the arrayconstfruitsCollection=[...fruits,'🍍','🥝']// Update the shoppingCart total and clone all the other propertiesconstshoppingCartWithTotal={...shoppingCart,total:15}
Enter fullscreen modeExit fullscreen mode

Object.freeze

TheObject.freeze function is a simple way to turn a mutableObject orArray into an "immutable value". This function freezes the object 🥶 you pass as argument.

But what doesfrozen object means? Afrozen object is an Object whose properties/indices has been marked as read-only and non-reconfigurable, so they can't be reassigned and the Object itself is marked as non-extensible, so no new properties can be added.

The freezing process ❄️ is only made at thetop level of the object. If you want to make your whole object immutable, make sure you deepfreeze each subObject orArray 🤓.

constfruits=Object.freeze(['🍌','🍓','🥥'])constshoppingCart=Object.freeze({id:'69zd841',total:0,products:[]})// We can't extend the fruits Array// ❌ TypeError: Cannot add property N, object is not extensiblefruits.push('🍏')// ❌ We can't mutate shoppingCart top-level properties// shoppingCart -> { id: '69zd841', total: 0, products: [] }shoppingCart.total=123// 🚨 We can mutate shoppingCart objects// shoppingCart -> { id: '69zd841', total: 0, products: [{ name: 'Beer' }] }shoppingCart.products.push({name:'Beer'})
Enter fullscreen modeExit fullscreen mode

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Lead Web Engineer @n26 • JavaScript, ReactJS and OpenSource ❤️
  • Location
    Barcelona
  • Work
    Lead Web Engineer at N26
  • Joined

More fromCarlos Cuesta

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp