Dec 18

New JS Array Methods

This year, a handful of new Array methods became available in all modern browsers: toReversed(), toSplice(), toSorted(), and with().

By Chris Ferdinandi

Let’s learn what these Array methods do and how they work!

Creating a reversed copy with the Array.prototype.toReversed() method

Let's say you have an array of wizards.

let wizards = ['Merlin', 'Ursula', 'Gandalf'];

The Array.prototype.reverse() method modifies the original array.

wizards.reverse();

// logs ["Gandalf", "Ursula", "Merlin"]
console.log(wizards);

Historically, if you wanted to create a reversed copy of the array instead of modifying the original, you would have to clone it first, then reverse it.

let reverseWizards = Array.from(wizards).reverse();

// logs ["Gandalf", "Ursula", "Merlin"]
console.log(reverseWizards);

// logs ["Merlin", "Ursula", "Gandalf"]
console.log(wizards);

The new Array.prototype.toReversed() method simplifies that into a single step.

let reverseWizards = wizards.toReversed();

// logs ["Gandalf", "Ursula", "Merlin"]
console.log(reverseWizards);

// logs ["Merlin", "Ursula", "Gandalf"]
console.log(wizards);

Here's a demo of the Array.prototype.toReversed() method.

Creating a spliced copy of an array with the Array.prototype.toSpliced() method

The Array.prototype.splice() method is used to add, remove, and replace items in an array. 

When using the method, the original array is modified.

The first argument is the index of the item you want to modify in the array and is the only required argument. The second argument is the number of items to delete from the array. It can be a number from 0 through the length of the array.

If you omit the second argument, the Array.prototype.splice() method will delete every item in the array from the start index on.

let wizards = ['Merlin', 'Ursula', 'Gandalf', 'Radagast'];

// This removes 1 item at index 2: "Gandalf"
// wizards is now ["Merlin", "Ursula", "Radagast"]
wizards.splice(2, 1);

Historically, if you want to keep the original array intact, you would clone it first, then splice() it.

let fewerWizards = Array.from(wizards).splice(2, 1);

The new Array.prototype.toSpliced() does the same thing as Array.prototype.splice() but creates a copy instead of modifying the original array.

let wizards = ['Merlin', 'Ursula', 'Gandalf', 'Radagast'];

let lessWizards = wizards.toSpliced(2, 1);

// logs ['Merlin', 'Ursula', 'Gandalf', 'Radagast']
console.log(wizards);

// logs ['Merlin', 'Ursula', 'Radagast']
console.log(lessWizards);

Here's a demo of the Array.prototype.toSpliced() method.

Creating a sorted copy of an array with the Array.prototype.toSorted() method

The Array.prototype.sort() method reorders the items in an array.

It modifies the original array and by default, will order the items alphanumerically.

let wizards = ['Merlin', 'Ursula of the Sea', 'Gandalf the Gray'];

wizards.sort();

// logs ['Gandalf the Gray', 'Merlin', 'Ursula of the Sea']
console.log(wizards);

You can optionally pass in a callback function that will modify the default sorting behavior.

The Array.prototype.sort() method loops through each item and passes two items at a time as arguments into the callback function. You can compare those two items and return an integer telling Array.sort() what to do with them.

If you return -1, it will place the first item before the second one. If you return 1, it will move the second item before the current one. If you return 0 (or nothing at all), it will leave them unchanged.

For example, let’s say we want to sort our wizards array by the length of the wizard’s name, with the longest names first. We could do this:

wizards.sort(function (wizard1, wizard2) {
// If wizard1 is longer, put it before wizard2
if (wizard1.length > wizard2.length) {
return -1;
}

// Otherwise, put wizard2 before wizard1
return 1;
});

// logs ['Ursula of the Sea', 'Gandalf the Gray', 'Merlin']
console.log(wizards);

The Array.prototype.toSorted() method works exactly the same way but creates a copy of the array before sorting it.

let sortedWizards = wizards.toSorted();

// logs ['Merlin', 'Ursula', 'Gandalf', 'Radagast']
console.log(wizards);

// logs ['Gandalf the Gray', 'Merlin', 'Ursula of the Sea']
console.log(sortedWizards);

Here’s a demo of the Array.prototype.toSorted() method.

Creating a copy of an array with a single value updated using the Array.prototype.with() method

To update a value in an array, you can use bracket notation ([]), passing in the index of the value to update.

Remember, array indexes start at 0.

let wizards = ['Merlin', 'Ursula', 'Gandalf'];

// Replaces "Gandalf" with "Radagast"
wizards[2] = 'Radagast';

// logs ['Merlin', 'Ursula', 'Radagast']
console.log(wizards);

The Array.prototype.with() method provides a simple way to copy an array and update one of its values in a single step.

You pass in the index to update and the value to assign to that index as arguments.

let differentWizards = wizards.with(2, 'Radagast');

// logs ['Merlin', 'Ursula', 'Gandalf']
console.log(wizards);

// logs ['Merlin', 'Ursula', 'Radagast']
console.log(differentWizards);

Here’s a demo of the Array.prototype.with() method.

Browser support and polyfills

The new Array methods we looked at today are now supported in all major browsers.

But… they’re relatively new, and not everyone updates their browsers regularly. In particular, browser updates on mobile devices are often tied to updating the entire OS. Someone running an older version of iOS, for example, won’t have support for these methods.

For now, I recommend using a polyfill that you can remove later when browser support gets better.

Polyfills are functions that check if a browser supports a method or API and recreate that method using older approaches if not. Unlike a helper function, they follow the spec for the new method and are designed to be deleted as browser support improves.

Here are polyfills you can use for the methods we discussed in this article.

// Polyfill: Array.prototype.toReversed()
if (!Array.prototype.toReversed) {
Array.prototype.toReversed = function () {
return Array.from(this).reverse();
};
}

// Polyfill: Array.prototype.toSpliced()
if (!Array.prototype.toSpliced) {
Array.prototype.toSpliced = function (...args) {
return Array.from(this).splice(...args);
};
}

// Polyfill: Array.prototype.toSorted()
if (!Array.prototype.toSorted) {
Array.prototype.toSorted = function (...args) {
return Array.from(this).sort(...args);
}
}

// Polyfill: Array.prototype.with()
if (!Array.prototype.with) {
Array.prototype.with = function (index, value) {
let clone = Array.from(this);
clone[index] = value;
return clone;
}
}

Wrapping up

We covered a lot in this article, so let’s quickly wrap up what we learned.

Chris selected Feeding America for an honorary donation of $50

Feeding America

Feeding America is the largest charity working to end hunger in the United States. We partner with food banks, food pantries, and local food programs to bring food to people facing hunger. We advocate for policies that create long-term solutions to hunger.