ECMAScript 2023 New Array Methods: toSorted, toReversed, toSpliced, and with
The ECMAScript 2023 specification introduces four new non‑mutating Array methods—toSorted, toReversed, toSpliced, and with—that let developers work on copies of arrays, improving predictability, easing React state updates, and providing consistent behavior across browsers and runtimes.
ECMAScript 2023 has been finalized, adding four new Array prototype methods— toSorted , toReversed , toSpliced and with —that return a new array instead of mutating the original, thereby increasing code predictability and maintainability.
Mutation and Side Effects
Traditional mutable methods such as sort , reverse and splice modify the array in place, while non‑mutating methods like concat , map and filter first create a copy. Mutating an array can cause side effects that lead to unexpected behavior elsewhere in the system.
For example, using reverse on an array mutates the original:
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const reversed = languages.reverse();
console.log(reversed); // => [ 'CoffeeScript', 'TypeScript', 'JavaScript' ]
console.log(languages); // => [ 'CoffeeScript', 'TypeScript', 'JavaScript' ]
console.log(Object.is(languages, reversed)); // => trueBoth variables reference the same mutated array.
Mutable Arrays and React
In React, mutating an array that is stored in state does not trigger a re‑render because the reference does not change. The recommended pattern is to copy the array first, then modify the copy before setting the new state.
Copy Then Mutate
Common ways to copy an array include Array.from , the spread operator, or slice() without arguments:
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const reversed = Array.from(languages).reverse();
console.log(languages); // => [ 'JavaScript', 'TypeScript', 'CoffeeScript' ]
console.log(Object.is(languages, reversed)); // => falseNew Methods Operate on Copies
The new methods automatically create a copy, apply the operation, and return the result, eliminating the need for an explicit copy step.
Array.prototype.toSorted
toSorted returns a new array that is sorted, leaving the original untouched.
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const sorted = languages.toSorted();
console.log(sorted); // => [ 'CoffeeScript', 'JavaScript', 'TypeScript' ]
console.log(languages); // => [ 'JavaScript', 'TypeScript', 'CoffeeScript' ]When sorting values with special characters, a comparator may still be required to obtain the expected order.
const numbers = [5, 3, 10, 7, 1];
const sorted = numbers.toSorted();
console.log(sorted); // => [ 1, 10, 3, 5, 7 ]
const sortedCorrectly = numbers.toSorted((a, b) => a - b);
console.log(sortedCorrectly); // => [ 1, 3, 5, 7, 10 ]Array.prototype.toReversed
toReversed returns a new array with the elements in reverse order.
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const reversed = languages.toReversed();
console.log(reversed); // => [ 'CoffeeScript', 'TypeScript', 'JavaScript' ]Array.prototype.toSpliced
toSpliced works like splice but returns a new array without mutating the original; it removes elements and can insert new ones.
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const spliced = languages.toSpliced(2, 1, "Dart", "WebAssembly");
console.log(spliced); // => [ 'JavaScript', 'TypeScript', 'Dart', 'WebAssembly' ]If you need the removed elements, combine toSpliced with slice on the original array.
const startDeletingAt = 2;
const deleteCount = 1;
const spliced = languages.toSpliced(startDeletingAt, deleteCount, "Dart", "WebAssembly");
const removed = languages.slice(startDeletingAt, startDeletingAt + deleteCount);
console.log(spliced); // => [ 'JavaScript', 'TypeScript', 'Dart', 'WebAssembly' ]
console.log(removed); // => [ 'CoffeeScript' ]Array.prototype.with
with creates a copy of the array and replaces the element at a given index.
const languages = ["JavaScript", "TypeScript", "CoffeeScript"];
const updated = languages.with(2, "WebAssembly");
console.log(updated); // => [ 'JavaScript', 'TypeScript', 'WebAssembly' ]
console.log(languages); // => [ 'JavaScript', 'TypeScript', 'CoffeeScript' ]Not Just Regular Arrays
The new methods are also available on any TypedArray (e.g., Int8Array , BigUint64Array ), although TypedArrays do not have a toSpliced equivalent because they lack a native splice method.
Caveats with Subclassed Arrays
When extending Array , built‑in non‑mutating methods ( map , filter , flatMap , concat ) preserve the subclass, but the new methods return a plain Array instance.
class MyArray extends Array {}
const languages = new MyArray("JavaScript", "TypeScript", "CoffeeScript");
const upcase = languages.map(l => l.toUpperCase());
console.log(upcase instanceof MyArray); // true
const reversed = languages.toReversed();
console.log(reversed instanceof MyArray); // falseYou can convert the result back to your subclass with MyArray.from :
const reversed = MyArray.from(languages.toReversed());
console.log(reversed instanceof MyArray); // trueSupport
Chrome 110, Safari 16.3, Node.js 20 and Deno 1.31 already support all four methods; other platforms can use polyfills or shims during the transition.
JavaScript Continues to Evolve
Beyond the new array methods, ES2023 also includes features such as Array.prototype.findLast , findLastIndex , hashbang syntax, and the ability to use Symbol keys in WeakMap . See the TC39 proposals repository for more details.
Appendix: ES2023 Feature Overview
Array.prototype.findLast / findLastIndex
let nums = [5,4,3,2,1];
let lastEven = nums.findLast(num => num % 2 === 0); // 2
let lastEvenIndex = nums.findLastIndex(num => num % 2 === 0); // 3Hashbang Syntax
#!/usr/bin/env node
// in the Script Goal
'use strict';
console.log(1);Using Symbols as WeakMap Keys
let sym = Symbol("foo");
let obj = {name: "bar"};
let wm = new WeakMap();
wm.set(sym, obj);
console.log(wm.get(sym)); // {name: "bar"}Reference: https://h3manth.com/ES2023/
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.