Door 22 | JS Adventskalender
Skip to content

Door 22

Published: at 07:00 AMSuggest Changes

Advanced Array Manipulation Methods in ES2023

Which New Methods Are These?

With ES2023 (ECMAScript 2023), JavaScript was expanded with four new array methods that significantly complement existing functionality:

  1. toReversed()
  2. toSorted()
  3. toSpliced()
  4. with()

They all have one thing in common: they do not mutate the array, but return a new copy with the corresponding changes. This non-destructive approach has proven successful in practice many times, especially in functional or reactive programming patterns where the immutability principle plays a major role. In this blog post, we’ll look at how they differ from already existing methods and how they can be used in everyday work.

Why New Methods?

Previously, JavaScript already had methods like reverse(), sort(), or splice(). Unfortunately, these methods have a crucial disadvantage: they mutate the array directly. If you want to keep an unchanged copy – for example, to preserve the original in a state management solution – you had to apply your own workarounds, such as cloning the array beforehand:

const original = [3, 1, 2];
const copy = [...original];  // Copy via spread
copy.sort((a, b) => a - b);
// copy -> [1, 2, 3], original -> [3, 1, 2]

With the new methods toReversed(), toSorted(), toSpliced(), and with(), JavaScript solves this problem by itself. Each of these methods creates a new version of the array and leaves the original array unchanged. This makes the code more readable, reduces sources of error, and follows the principles of immutable data processing.

Let’s now turn to the individual new methods and take a closer look at them.

1. toReversed()

What does it do?

Similar to reverse(), toReversed() sorts an existing array in reverse order. However, it does not destroy the original array but creates a new array. As already described, it creates a copy of the array in reverse order.

Example:

const original = [1, 2, 3];
const reversed = original.toReversed();

console.log(original); // [1, 2, 3] - unchanged
console.log(reversed); // [3, 2, 1] - new array

Comparison with reverse():

const arr = [1, 2, 3];
arr.reverse(); // Mutates the original array
console.log(arr); // [3, 2, 1]

const arr2 = [1, 2, 3];
const reversed = arr2.toReversed(); // Returns new array
console.log(arr2); // [1, 2, 3] - unchanged
console.log(reversed); // [3, 2, 1]

2. toSorted()

What does it do?

Works analogously to sort(), but returns a sorted copy of the array instead of modifying the original.

Example:

const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
const sorted = numbers.toSorted((a, b) => a - b);

console.log(numbers); // [3, 1, 4, 1, 5, 9, 2, 6] - unchanged
console.log(sorted);  // [1, 1, 2, 3, 4, 5, 6, 9]

Use Case:

const users = [
  { name: 'Charlie', age: 30 },
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 35 }
];

const sortedByAge = users.toSorted((a, b) => a.age - b.age);
const sortedByName = users.toSorted((a, b) => a.name.localeCompare(b.name));

console.log(users); // Original order unchanged
console.log(sortedByAge); // Sorted by age
console.log(sortedByName); // Sorted by name

3. toSpliced()

What does it do?

Analogous to splice(), but returns a new array with the changes instead of modifying the original.

Example:

const items = ['a', 'b', 'c', 'd', 'e'];
const spliced = items.toSpliced(2, 2, 'X', 'Y');

console.log(items);   // ['a', 'b', 'c', 'd', 'e'] - unchanged
console.log(spliced); // ['a', 'b', 'X', 'Y', 'e']

Parameters:

More Examples:

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

// Remove elements
const removed = arr.toSpliced(2, 2);
console.log(removed); // [1, 2, 5]

// Insert elements
const inserted = arr.toSpliced(2, 0, 'a', 'b');
console.log(inserted); // [1, 2, 'a', 'b', 3, 4, 5]

// Replace elements
const replaced = arr.toSpliced(1, 2, 'X', 'Y');
console.log(replaced); // [1, 'X', 'Y', 4, 5]

4. with()

What does it do?

Returns a new array with a single element changed at a specific index.

Example:

const colors = ['red', 'green', 'blue'];
const updated = colors.with(1, 'yellow');

console.log(colors);  // ['red', 'green', 'blue'] - unchanged
console.log(updated); // ['red', 'yellow', 'blue']

Comparison with direct assignment:

// Old way (mutating)
const arr = [1, 2, 3];
arr[1] = 99;
console.log(arr); // [1, 99, 3] - original changed

// New way (immutable)
const arr2 = [1, 2, 3];
const updated = arr2.with(1, 99);
console.log(arr2);    // [1, 2, 3] - unchanged
console.log(updated); // [1, 99, 99]

Practical Benefits

1. Immutable State Updates:

// In React/Redux style state management
const state = {
  items: [1, 2, 3]
};

// Instead of:
const newItems = [...state.items];
newItems[1] = 99;

// Simply:
const newState = {
  ...state,
  items: state.items.with(1, 99)
};

2. Method Chaining:

const numbers = [5, 2, 8, 1, 9];

const result = numbers
  .toSorted((a, b) => a - b)
  .toReversed()
  .toSpliced(0, 2)
  .with(0, 100);

console.log(numbers); // [5, 2, 8, 1, 9] - unchanged
console.log(result);  // [100, 5, 2]

3. No Side Effects:

function processData(data) {
  return data
    .toSorted()
    .toSpliced(0, 1) // Remove first element
    .with(0, 'FIRST'); // Change first element
}

const original = [3, 1, 4, 1, 5];
const processed = processData(original);

console.log(original); // [3, 1, 4, 1, 5] - never changed
console.log(processed); // ['FIRST', 1, 3, 4, 5]

Conclusion

The new array methods in ES2023 bring immutability directly into the language. They make functional programming patterns easier, reduce bugs from unexpected mutations, and improve code readability. While they are still relatively new, they represent an important step toward more maintainable JavaScript code.

Use these new immutable array methods in your next project and enjoy safer, more predictable code!


Previous Post
Door 23
Next Post
Door 21