Immutable Array MethodsLoading saved progress…

Immutable Array Methods

The ES2023 change-by-copy methods — toSorted, toReversed, and with — each return a new array instead of editing the one you called them on. They are the non-mutating twins of sort(), reverse(), and index assignment (arr[i] = x), which all rewrite the original array in place. Reaching for a copy is safer in code that shares arrays across a UI or a store, where a hidden in-place edit shows up as a bug somewhere else. You can read the spec on MDN.

Implement the three as standalone functions that each take the array as the first argument, return a new array, and never mutate the input.

Signature

toSorted(arr, compareFn?)   // a sorted copy of arr
toReversed(arr)             // a reversed copy of arr
with(arr, index, value)     // a copy of arr with the slot at index replaced by value

Examples

toSorted([3, 1, 2], (a, b) => a - b); // [1, 2, 3]   (input still [3, 1, 2])
toSorted([10, 2, 1]);                 // [1, 10, 2]  (default sort is by string!)
toReversed([1, 2, 3]);                // [3, 2, 1]
with([1, 2, 3], 1, 9);                // [1, 9, 3]
with([1, 2, 3], -1, 9);               // [1, 2, 9]   (-1 is the last slot)
with([1, 2, 3], 3, 9);                // throws RangeError (index === length)

Notes

  • Never mutate — each method returns a brand-new array, and the input array must read exactly as it did before the call.
  • Default sort is lexicographic — with no compareFn, toSorted compares elements as strings by code unit, so [10, 2, 1] sorts to [1, 10, 2]. A compareFn(a, b) overrides that.
  • Sorting is stable — elements the comparator calls equal keep their original relative order.
  • Negative indexwith treats a negative index as counting from the end; the real index is index + length, so -1 is the last slot.
  • Bounds check — after normalizing, with throws a RangeError if the index is < 0 or >= length.
  • Do not use the built-ins — build the behavior yourself; do not call the real Array.prototype.toSorted, toReversed, or with.

FAQ

Do toSorted, toReversed, and with mutate the original array?
No. Each one returns a brand-new array and leaves the input untouched. That is the whole point of the ES2023 change-by-copy methods, unlike sort(), reverse(), and index assignment, which change the array in place.
Why does toSorted([10, 2, 1]) return [1, 10, 2] instead of [1, 2, 10]?
With no comparator, sort converts every element to a string and compares by UTF-16 code unit, so '10' sorts before '2'. Pass a comparator such as (a, b) => a - b to get numeric order.
How does with() handle a negative index?
A negative index counts from the end, so -1 targets the last element (the real index is index + length). If the normalized index is still out of range, with() throws a RangeError.
Loading editor…