Finally, safe array methods in JavaScript

There’s a good reason that many developers pause before using .sort(), .reverse(), or .splice() in JavaScript: those methods mutate the original array. That single side effect can lead to subtle, hard-to-trace bugs, especially in apps with shared or reactive state. The good news is that in the last couple of years we’ve gotten new array methods that make working with arrays safer and cleaner by avoiding mutation altogether:

  • toSorted()
  • toReversed()
  • toSpliced()

These return copies instead of changing the original array. It’s a small syntax upgrade with big implications, especially for React developers who rely on immutability to manage state.

The problem with in-place array methods

In JavaScript, traditional methods like .sort(), .reverse(), and .splice() mutate the array they’re called on:

const numbers = [3, 1, 2];
numbers.sort(); console.log(numbers); 

In frameworks like React, this can lead to unexpected behavior when updating state, because mutating arrays directly doesn’t trigger re-renders.

Comparing old vs. new

Operation Mutating method Non-mutating alternative
Sort arr.sort() arr.toSorted()
Reverse arr.reverse() arr.toReversed()
Splice arr.splice() arr.toSpliced()

These new methods behave similarly to their mutating counterparts, but return a new array instead of modifying the original.

⚠️ Note: These are shallow copies, so if your array contains objects, the objects themselves are still the same references.

The solution: safe, non-mutating methods

ES2023 introduced non-mutating versions of these familiar array methods:

toSorted()

Creates a sorted copy of the array without changing the original.

const numbers = [3, 1, 2];
const sorted = numbers.toSorted(); console.log(sorted); console.log(numbers); numbers.sort();
console.log(numbers); 

You can also pass a custom compare function, just like .sort():

const users = [ { name: 'Kristen', age: 36 }, { name: 'David', age: 34 },
]; const byAge = users.toSorted((a, b) => a.age - b.age); console.log(byAge); console.log(users); 

toReversed()

Returns a reversed copy of the array:

const names = ['Kristen', 'David', 'Ben'];
const reversed = names.toReversed(); console.log(reversed); console.log(names); names.reverse();
console.log(names);    

Perfect when you want to display a list in reverse order without modifying the source array.

toSpliced()

A safer alternative to .splice(). It returns a new array with elements added/removed, but doesn’t touch the original:

const items = ['a', 'b', 'c', 'd']; const withoutB = items.toSpliced(1, 1); console.log(withoutB); console.log(items); const withX = items.toSpliced(2, 0, 'x');
console.log(withX); const items2 = ['a', 'b', 'c', 'd'];
const removed = items2.splice(1, 1);
console.log(removed); console.log(items2);   

Reminder: .splice() returns the removed items, while .toSpliced() returns the updated array.

Why this matters in React

In React, immutability is key for triggering component updates and preserving state predictability.


state.items.sort(); const sortedItems = state.items.toSorted();
setState({ items: sortedItems }); 

These new methods help ensure you’re treating arrays as immutable, without needing structuredClone() or deep-copy workarounds.

Real-world example: sorting tasks in React

Here’s how you might use toSorted() or toReversed() in a component to safely display dynamic lists:

function TaskList({ tasks }) { const recentFirst = tasks?.toReversed() ?? []; return ( <ul> {recentFirst.map((task) => ( <li key={task.id}>{task.title}</li> ))} </ul> );
}

This avoids mutating tasks, which could cause bugs if it’s a prop or derived from state. The optional chaining (?.) and nullish coalescing (??) operators also help avoid errors if tasks is undefined.

Both optional chaining and nullish coalescing are terrific syntax upgrades I’ve written about that help bring your code into a future-proof style that avoids common runtime pitfalls.

A tiny syntax change, a big win

These methods don’t require any new mental model, they’re just immutable-safe versions of what you already use. If you’re working in modern environments (or with a build step like Babel or SWC), you can start using them today.

Browser support

toSorted(), toReversed(), and toSpliced() are supported in all modern environments (Chrome/Edge 110+, Safari 16+, Firefox 115+, Node.js 20+). For legacy environments, you can use a polyfill like core-js.

Key takeaways

Method What it does Mutates original?
.toSorted() Returns a sorted copy
.toReversed() Returns a reversed copy
.toSpliced() Returns modified copy (add/remove elements)

ES2023 didn’t just give us flashy syntax like optional chaining or top-level await, but these subtle additions can massively improve code clarity and reduce bugs, especially in modern front-end workflows.

Start using them in your projects, and you’ll never look at .sort() with the same trust again.

trang chủ - Wiki
Copyright © 2011-2025 iteam. Current version is 2.146.0. UTC+08:00, 2025-09-19 11:08
浙ICP备14020137号-1 $bản đồ khách truy cập$