Non-Mutating Array Methods in JavaScript
JavaScript introduced a set of non-mutating array methods in
ECMAScript 2023 (ES14) that allow developers to transform arrays without
altering the original data. Traditional methods like
sort(), reverse(), and splice()
mutate arrays in place, which can cause unintended side effects and bugs
in state-driven applications. The newer
alternatives—toSorted(), toReversed(),
toSpliced(), and with()—create and return a
shallow copy of the array with the requested changes applied, keeping
the original array intact.
Why Non-Mutating Methods Matter
In functional programming and modern frameworks like React, state
immutability is crucial. Previously, to avoid mutating an array, you had
to manually create a copy using the spread operator
([...arr]) or Array.prototype.slice() before
performing operations:
// Old approach
const original = [3, 1, 2];
const sorted = [...original].sort();The new methods eliminate this boilerplate by handling the copying process internally.
Array.prototype.toSorted()
The toSorted() method is the immutable counterpart to
sort(). It returns a new array with the elements sorted in
ascending order or according to a provided comparator function.
const numbers = [40, 10, 30, 20];
// Sorts without mutating 'numbers'
const sortedNumbers = numbers.toSorted((a, b) => a - b);
console.log(sortedNumbers); // [10, 20, 30, 40]
console.log(numbers); // [40, 10, 30, 20]Array.prototype.toReversed()
The toReversed() method is the non-mutating equivalent
of reverse(). It produces a new array with elements in the
inverted sequence.
const letters = ['a', 'b', 'c', 'd'];
// Reverses without mutating 'letters'
const reversedLetters = letters.toReversed();
console.log(reversedLetters); // ['d', 'c', 'b', 'a']
console.log(letters); // ['a', 'b', 'c', 'd']Array.prototype.toSpliced()
The toSpliced() method replaces splice()
when immutability is required. While splice() modifies the
target array and returns the deleted elements, toSpliced()
returns a completely new array with the additions, removals, or
replacements applied.
Its syntax is:
toSpliced(start, deleteCount, ...items)
const months = ['Jan', 'Mar', 'Apr', 'May'];
// Insert 'Feb' at index 1 without mutating 'months'
const fullMonths = months.toSpliced(1, 0, 'Feb');
console.log(fullMonths); // ['Jan', 'Feb', 'Mar', 'Apr', 'May']
console.log(months); // ['Jan', 'Mar', 'Apr', 'May']Array.prototype.with()
The with() method offers a non-mutating way to update a
single value at a specific index. Instead of using bracket notation
(such as arr[index] = value), which mutates the array,
with() returns a copy containing the updated item.
Its syntax is: with(index, value)
const scores = [85, 90, 78];
// Update the score at index 2 without mutating 'scores'
const updatedScores = scores.with(2, 95);
console.log(updatedScores); // [85, 90, 95]
console.log(scores); // [85, 90, 78]Negative indices are also supported, where -1 represents
the last item in the array.
Summary
The toSorted(), toReversed(),
toSpliced(), and with() methods make data
transformations safer and more expressive in JavaScript. By handling
array duplication automatically, they simplify code, prevent accidental
side effects, and integrate seamlessly into immutable programming
workflows.