Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Immutability

Immutability is an approach in which data is not changed in place; instead, an updated copy is created. This makes bugs easier to track down: an object cannot suddenly change because of code at the other end of the program. React and many other libraries are built on this approach.

Primitives do not change

Strings, numbers and other primitives are immutable. String methods do not touch the original string; they return a new one:

const word = 'cat';
const upper = word.toUpperCase();
 
console.log(word); // cat
console.log(upper); // CAT

Objects are passed by reference

Objects and arrays are different. A variable holds not the object itself but a reference to it, so two variables can point to the same object:

const anna = { score: 1 };
const player = anna;
 
player.score = 2;
 
console.log(anna.score); // 2

const does not help here: it forbids assigning another value to the variable, but it does not stop you from changing the object's contents.

Updating through a copy

Instead of changing an object, you create a new one with the edits. The spread operator ... copies the old properties, and the new ones follow:

const user = { name: 'Anna', age: 28 };
const older = { ...user, age: 29 };
 
console.log(user.age); // 28
console.log(older.age); // 29

The same goes for arrays: [...list, item] instead of list.push(item).

Array methods without mutation

Some array methods change the original array. They have counterparts that return a copy:

Changes the arrayReturns a copy
sort()toSorted()
reverse()toReversed()
splice()toSpliced()
arr[i] = xarr.with(i, x)
const numbers = [3, 1, 2];
const sorted = numbers.toSorted();
 
console.log(numbers.join(', ')); // 3, 1, 2
console.log(sorted.join(', ')); // 1, 2, 3

Object.freeze

Object.freeze() "freezes" an object: its properties can no longer be changed, added or removed. An attempt is silently ignored, and in strict mode it throws an error:

const config = Object.freeze({ currency: '€' });
 
config.currency = '$';
 
console.log(config.currency); // €

Freezing is shallow

Object.freeze() works only on the top level: nested objects and arrays stay mutable. A complete independent copy with all nested data is made by the structuredClone() function:

const order = { items: ['tea'] };
const copy = structuredClone(order);
 
copy.items.push('coffee');
 
console.log(order.items.length); // 1
console.log(copy.items.length); // 2

Spread also copies only the top level: in a { ...order } copy the items array would be the very same one.

Common mistake

Thinking that sort() returns a sorted copy. It sorts the array itself, and the original order is lost:

const prices = [30, 10, 20];
const sorted = prices.sort((a, b) => a - b);
 
console.log(prices.join(', ')); // 10, 20, 30
console.log(sorted === prices); // true

If you still need the original array, use toSorted() or sort a copy: [...prices].sort().

Thanks for reading!

Donate to the site — we work hard for you.