Immutable Array Patterns (ES2023)

Med

Immutable array operations create new arrays instead of modifying the original. This is essential for functional programming, React state updates, and avoiding side effects. ES2023 added new immutable methods: toSorted(), toReversed(), toSpliced(), and with(). Learn patterns for adding, removing, and updating elements immutably.

Interactive Visualization

mutation Methods

1
2
3

Key Points

  • Immutable operations return new arrays
  • Spread operator [...arr] for shallow copies
  • ES2023: toSorted(), toReversed(), toSpliced(), with()
  • filter() for removing elements immutably
  • map() for updating elements immutably
  • slice() and spread for inserting elements

Code Examples

ES2023 Immutable Methods

const arr = [3, 1, 4, 1, 5];

// toSorted - immutable sort
const sorted = arr.toSorted((a, b) => a - b);
console.log(sorted);  // [1, 1, 3, 4, 5]
console.log(arr);     // [3, 1, 4, 1, 5] - unchanged!

// toReversed - immutable reverse
const reversed = arr.toReversed();
console.log(reversed);  // [5, 1, 4, 1, 3]

// toSpliced - immutable splice
const spliced = arr.toSpliced(1, 2, 'a', 'b');
console.log(spliced);  // [3, 'a', 'b', 1, 5]

// with - replace element at index
const replaced = arr.with(2, 'x');
console.log(replaced);  // [3, 1, 'x', 1, 5]

ES2023 adds immutable versions of mutating methods. All return new arrays.

Add Elements Immutably

const arr = [1, 2, 3];

// Add to end
const addEnd = [...arr, 4];
console.log(addEnd);  // [1, 2, 3, 4]

// Add to beginning
const addStart = [0, ...arr];
console.log(addStart);  // [0, 1, 2, 3]

// Insert at index
const insertAt2 = [...arr.slice(0, 2), 'x', ...arr.slice(2)];
console.log(insertAt2);  // [1, 2, 'x', 3]

// Or use toSpliced (ES2023)
const insertES2023 = arr.toSpliced(2, 0, 'x');
console.log(insertES2023);  // [1, 2, 'x', 3]

Use spread with slice for immutable insertion at any position.

Remove Elements Immutably

const arr = [1, 2, 3, 4, 5];

// Remove by value
const without3 = arr.filter(x => x !== 3);
console.log(without3);  // [1, 2, 4, 5]

// Remove by index
const removeAt2 = [...arr.slice(0, 2), ...arr.slice(3)];
console.log(removeAt2);  // [1, 2, 4, 5]

// Remove first
const [, ...rest] = arr;
console.log(rest);  // [2, 3, 4, 5]

// Remove last
const withoutLast = arr.slice(0, -1);
console.log(withoutLast);  // [1, 2, 3, 4]

// Or use toSpliced
const removedES2023 = arr.toSpliced(2, 1);  // Remove 1 element at index 2
console.log(removedES2023);  // [1, 2, 4, 5]

Use filter to remove by value, slice/spread to remove by index.

Update Elements Immutably

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Carol' }
];

// Update one element
const updated = users.map(user =>
  user.id === 2
    ? { ...user, name: 'Bobby' }  // New object for changed item
    : user  // Unchanged reference
);

console.log(updated[1]);  // { id: 2, name: 'Bobby' }
console.log(users[1]);    // { id: 2, name: 'Bob' } - unchanged!

// Or use with() for simple arrays
const nums = [1, 2, 3, 4];
const newNums = nums.with(1, 99);
console.log(newNums);  // [1, 99, 3, 4]

Use map to update elements, spreading to create new objects. with() for simple value replacement.

Common Mistakes

  • Using mutating methods when immutability is needed (React state)
  • Creating deep copies when shallow is sufficient
  • Not realizing spread is shallow (nested objects still shared)
  • Using JSON.parse/stringify for deep copy (loses functions, dates)

Interview Tips

  • Know ES2023 immutable methods
  • Understand shallow vs deep copy
  • Know patterns for add/remove/update immutably
  • Know structuredClone() for deep copy