The Use-Case-Driven Guide to Essential JavaScript Array Methods
Table of contents:
When working with arrays, it can be easy to reinvent the wheel.
Once you know how to iterate over an array with a for
loop, you can sink into the trap of using it every time you’re working with arrays.
Any why shouldn’t you? After all, it’s a versatile, easily understood concept.
The importance of logical shorthands
When a pattern occurs frequently across many different types of programs, developers create utility functions for handling those patterns.
Not only does this cut down on duplicate code, but the semantics helps other developers understand your intent more easily.
You can write a loop that filters an array, but when I see Array.filter
I immediately know what you’re trying to do.
How does this guide work?
I’ve gone through the instance methods of JavaScript arrays and organized them by category, leaving out the ones that I consider to be less commonly used.
Did I leave out your favorite array method? Let me know in the comments!
Sample Data
The below sample data is used throughout this post. To maintain consistency, each example starts with the assumption that this data has not been modified.
// Some Hosts of Great British Bake Off
const hosts = [
{ id: 1, name: 'Paul Hollywood', isBaker: true },
{ id: 2, name: 'Prue Leith', isBaker: true },
{ id: 3, name: 'Noel Fielding', isBaker: false },
{ id: 4, name: 'Matt Lucas', isBaker: false },
];
// Some Winners of Great British Bake Off
const winners = [
'Edd Kimber',
'Joanne Wheatley',
'John Whaite',
'Frances Quinn',
];
Testing or looking for existing elements
Find the first element that satisfies a condition
find
accepts a function and returns the first element for which that function returns a truthy value.
const paul = hosts.find(host => host.name === 'Paul Hollywood');
// { id: 1, name: 'Paul Hollywood', isBaker: true }
const firstNonBaker = hosts.find(host => !host.isBaker);
// { id: 3, name: 'Noel Fielding', isBaker: false }
Find the index of the first element that satisfies a condition
This method works the same way as find
, except it returns the element’s index instead of the elements itself.
const paulIndex = hosts.findIndex(host => host.name === 'Paul Hollywood');
// 0
Find the index of an element
indexOf
differs slightly from findIndex
in that it accepts an exact value as its parameter rather than function. Because of this, it’s more useful for primitive values since objects are compared by reference.
If the element occurs more than once in the array, the index of the first occurrence is returned.
If the element is not in the array, then -1
is returned.
const indexOfJohn = winners.indexOf('John Whaite');
// 2
const indexOfMe = winners.indexOf('Adam Davis');
// -1
// This methods compares objects by reference rather than by value, so it's
// more useful with primitive types than with objects.
const originalPaul = hosts[0];
const paulClone = { id: 1, name: 'Paul Hollywood', isBaker: true };
const indexOfOriginalPaul = hosts.indexOf(originalPaul);
// 0
const indexOfPaulClone = hosts.indexOf(paulClone);
// -1
Find the last index of an element
This is the same as indexOf
except it returns the index of the last occurrence of an element except the first occurrence of an element.
Find every element that satisfies a condition
const bakers = hosts.filter(host => host.isBaker);
// [ { id: 1, name: 'Paul Hollywood', isBaker: true }, { id: 2, name: 'Prue Leith', isBaker: true } ]
Test whether every element satisfies a condition
const isAllBakers = hosts.every(host => host.isBaker);
// false
Test whether at least one element satisfies a condition
const hasAtLeastOneBaker = hosts.some(host => host.isBaker);
// true
const hasAtLeastOneIdGreaterThanTen = hosts.some(host => host.id > 10);
// false
Test whether an element is included in an array
// This methods compares objects by reference rather than by value, so it's
// more useful with primitive types than with objects.
const originalPaul = hosts[0];
const paulClone = { id: 1, name: 'Paul Hollywood', isBaker: true };
const containsOriginalPaul = hosts.includes(originalPaul);
// true
const containsPaulClone = hosts.includes(paulClone);
// false
Manipulating arrays
Note: Each of these examples assumes the array is in the original state and has not been changed by another example
Add an element to the end of an array
hosts.length;
// 4
hosts.push({id: 5, name: 'Sue Perkins'});
hosts.length;
// 5
// This method accepts an arbitrary number of arguments, meaning you can add as
// many elements as you want with a single call
winners.length;
// 4
winners.push('Nancy Birtwistle', 'Nadiya Hussain', 'Candice Brown');
winners.length;
// 7
While this is not the only use case for concat
, it can be used in the same way as push. The difference, however, is that concat is non-destructive. This means that it returns a new array instead of the overwriting the existing array.
winners.length;
// 4
const moreWinners = winners.concat('Nancy Birtwistle', 'Nadiya Hussain', 'Candice Brown');
winners.length;
// 4
moreWinners.length;
// 7
Remove the last element from an array
This method is the inverse of push
, removing the last element from an array. Using these two functions, you can treat an array like a stack.
hosts.length;
// 4
const lastElement = hosts.pop();
// { id: 4, name: 'Matt Lucas', isBaker: false }
hosts.length;
// 3
Combine two arrays
winners.length;
// 4
otherWinners = ['Sophie Faldo', 'Rahul Mandal'];
combinedWinners = winners.concat(otherWinners);
Set all (or just some) elements to the same value
winners.fill('everyone');
// [ 'everyone', 'everyone', 'everyone', 'everyone' ]
winners.fill('you', 0, 2);
// [ 'you', 'you', 'everyone', 'everyone' ]
Sort an array
winners.sort();
// [ 'Edd Kimber', 'Frances Quinn', 'Joanne Wheatley', 'John Whaite' ]
Reverse the order of an array
winners;
// [ 'Edd Kimber', 'Joanne Wheatley', 'John Whaite', 'Frances Quinn' ]
winners.reverse();
// [ 'Frances Quinn', 'John Whaite', 'Joanne Wheatley', 'Edd Kimber' ]
Reduce the depth of an array (unnest an array of arrays)
let bothArrays = [hosts, winners];
// [
// [
// { id: 1, name: 'Paul Hollywood', isBaker: true },
// { id: 2, name: 'Prue Leith', isBaker: true },
// { id: 3, name: 'Noel Fielding', isBaker: false },
// { id: 4, name: 'Matt Lucas', isBaker: false }
// ],
// [ 'Edd Kimber', 'Joanne Wheatley', 'John Whaite', 'Frances Quinn' ]
// ]
bothArrays.flat();
// [
// { id: 1, name: 'Paul Hollywood', isBaker: true },
// { id: 2, name: 'Prue Leith', isBaker: true },
// { id: 3, name: 'Noel Fielding', isBaker: false },
// { id: 4, name: 'Matt Lucas', isBaker: false },
// 'Edd Kimber',
// 'Joanne Wheatley',
// 'John Whaite',
// 'Frances Quinn'
// ]
Iterating over or performing functions on elements of an array
Get the results of passing each element into a function
const hostNames = hosts.map(host => host.name);
// [ 'Paul Hollywood', 'Prue Leith', 'Noel Fielding', 'Matt Lucas' ]
flatMap
works the same way as map
, but flattens the array afterwards.
const hostNamesSeparated = hosts.flatMap(host => host.split(' '));
// [
// 'Paul', 'Hollywood',
// 'Prue', 'Leith',
// 'Noel', 'Fielding',
// 'Matt', 'Lucas'
// ]
Iterating over every element
hosts.forEach(host => console.log(host.name));
// Paul Hollywood
// Prue Leith
// Noel Fielding
// Matt Lucas
Reduce an array into a single value
I think reduce
is usually a good candidate for replacing a for
loop when there’s a variable declared right before the loop, and the main purpose of the loop is to accumulate some value in that variable.
// The for loop you might want to replace
let numberOfBakers = 0;
for (let i = 0; i < hosts.length; i++) {
numberOfBakers = numberOfBakers + ~~hosts[i].isBaker;
// ~~ is used to convert values to numbers without allowing for NaN
}
let numberOfBakers = hosts.reduce((accumulator, host) => accumulator + ~~host.isBaker, 0);
// 2
Creating string representations
join
creates a string representation of the array, delimiting each item using the given string argument.
winners.join(', ');
// 'Edd Kimber, Joanne Wheatley, John Whaite, Frances Quinn'
winners.toString();
// 'Edd Kimber,Joanne Wheatley,John Whaite,Frances Quinn'
If you liked this post, click here to subscribe to my mailing list!