Javascript Array Methods. All you really need to know.
Walter Miani
Posted on April 25, 2022
The idea of this post is to show you the minimum set of methods you need to deal with to get away with any array-related problems you might encounter on an average development day.
And when I say any problem I obviously mean the 99% of ’em…there will always be something absurd that the human mind has not yet learned to solve with simple ideas.
Who is this post for? This is for someone who is starting to get comfortable with javascript but isn’t a ninja yet. It is for those looking for a summary of what to know and use when working with arrays, to create a solid foundation from which to start your journey through becoming a javascriptmegaexpert.
Oh, if I talk bullshit let me know.
Table of contents
Level 1
Level 2
Level 3
Level 4
Bonus
So, there are tons of array instance methods.
…at, concat, copyWithin, entries, every, fill, filter, find, findIndex, flat, flatMap, foreach, includes, indexOf, join, keys, lastIndexOf, map, pop, push, reduce, reverse, shift, slice, some, sort, splice, toLocaleString, toString, unshift, values…
and maybe I left out something.
But… what do you REALLY need to know to cover all your array necessities?
After 5+ years of experience with Javascript I’m gonna tell you which ones I use the most and show you some interesting use cases.
They’ll be divided into frequencies of use.
LEVEL 1 - used every 3 to 4 minutes
push
It just adds one or more values at the end of an array. Easy Peasy.
var array = []
array.push(1)
array.push(2,3,4)
array.push(...[5,6,7])
console.log(array) // [ 1, 2, 3, 4, 5, 6, 7 ]
Just keep in mind that when you add more than one element you don’t have to pass an array of elements as the argument of the push method, but rather all the elements you want to add separately (which as you can see in the example before can be done with the ...
operator)
If you pass an array, it will add an array in the array.
var array = []
array.push([1,2,3])
array.push(...[4,5,6])
console.log(array) // [ [ 1, 2, 3 ], 4, 5, 6 ]
console.log('array has ' + array.length + ' elements') // 'array has 4 elements'
I don’t remember myself using push to add more than one value at the time to an array in the last months. Just remember that there is also this possibility.
forEach
Basically do something for every element of an array... you choose what.
var array = ['pizza', 'pasta', 'chicken', 'cake']
console.log('Menu')
array.forEach((el,index) => {
console.log(index+1 + ' - ' + el.toUpperCase())
})
// output
/*
'Menu'
'1 - PIZZA'
'2 - PASTA'
'3 - CHICKEN'
'4 - CAKE'
*/
It’s a loop function, so it processes every element of the array, in order, separately.
syntax: a callback that takes 2 parameters, the first is the current element, the second is the index of the element in the array (it can actually take also a third parameter, which is the whole array itself, but I’ve never ever used it)
It does not return anything, you just use it to do something for every element of the array.
I normally don’t use forEach to modify elements of the array, for that purpose I would use the next method…
map
same syntax as forEach, you’ll need a callback with 1 or 2 arguments. The difference is that map returns a new array of the exact dimension of the starting array (obviously)… the value of each new element is the return value of the callback.
var array = [1,2,3,4,5,6,7,8,9]
var out = array.map((el,i) => {
return el*2
})
console.log(out) // [ 2, 4, 6, 8, 10, 12, 14, 16, 18 ]
filter
Use filter when you have an array but at some point you need only some of its elements.
It returns a new array which elements are all the elements that passes the test you provide as callback, same old syntax.
Here, the ‘survivor’ elements are those that make the callback return TRUE.
var array = [{food: 'pizza', price: 11}, {food: 'chicken', price: 13}, {food: 'icecream', price: 3}, {food: 'soup', price: 7}]
var onlyCheapFood = array.filter(f => f.price < 10)
console.log(onlyCheapFood)
// [
// { food: 'icecream', price: 3 },
// { food: 'soup', price: 7 }
// ]
A quite recurrent and useful application of filter is the following:
You have a table, and it needs an array of data as its input source. Along with the table comes a search input of some sort (either global or on one of the columns of the table) that allows you to filter the data (sorry, I had to use the word filter to explain what the method filter does).
So the table does not get the original array of data as input but a “filteredArray” based on the search input value.
If the search parameter are not set, the filteredArray is simply equivalent to the original array.
var data = [{product: 'trousers', price: 100},
{product: 't-shirt', price: 15},
{product: 'shoes', price: 55},
{product: 'shirt', price: 80},
{product: 'socks', price: 12},
{product: 'hat', price: 22}]
const getDataForTable = (data, limit) => {
return !limit? data: data.filter(d => d.price < limit)
}
var costLimit = 30
var filteredData1 = getDataForTable(data, costLimit)
var filteredData2 = getDataForTable(data)
console.log(filteredData1)
/*
[
{ product: 't-shirt', price: 15 },
{ product: 'socks', price: 12 },
{ product: 'hat', price: 22 }
] */
console.log(filteredData2)
/*
[
{ product: 'trousers', price: 100 },
{ product: 't-shirt', price: 15 },
{ product: 'shoes', price: 55 },
{ product: 'shirt', price: 80 },
{ product: 'socks', price: 12 },
{ product: 'hat', price: 22 }
]
*/
Beware: in case of arrays with great numbers of elements you probably better manage the filtering operation via backend (and maybe some sort of pagination), but we’re not gonna cover this in this post.
Beware part 2: in case of arrays of objects, filter does a shallow copy. So if then something changes in the original array, you'll find the edited value also in the new array.
You can avoid this by applying a map() to the filtered array. Here is an example.
var a = [{value: 1}, {value: 3}, {value: 1}]
var b = a.filter(o => o.value == 1)
var c = a.filter(o => o.value == 1).map(e => {return {...e}})
a[0].value = 2
console.log(b)
/*
[ { value: 2 }, { value: 1 } ]
*/
console.log(c)
/*
[ { value: 1 }, { value: 1 } ]
*/
mixed examples
filter can be also used to thin out an array if you don’t need the original dataset, and can be concatenated multiple times in a row (like a pipeline).
Other methods like map can be added to the pipeline.
Here are some examples:
var func1 = a => a.length > 6
var func2 = a => a[0] == 'p'
var array = ['pizza', 'pepperoni', 'chicken', 'salami','pineapple', 'pasta', 'ice']
array = array.filter(func1).filter(func2)
console.log(array) // [ 'pepperoni', 'pineapple' ]
var func1 = a=> a.length > 6
var func2 = a => a[0] == 'p'
var func3 = a => a.slice(-1)[0] == 'e'
var func4 = a => a.length < 15
var array = ['pizza', 'pepperoni', 'chicken', 'salami','pineapple', 'pasta', 'ice', 'pizza with a lot of cheese']
var filters = [func1,func2,func3,func4]
filters.forEach(f => {
array = array.filter(f)
})
console.log(array) // [ 'pineapple' ]
// take only even numbers and show their square
var array = [1,2,3,4,5,6,7,8,9,10]
var out = array.filter(n => n%2 == 0).map(n => n*n)
console.log(out) // [ 4, 16, 36, 64, 100 ]
LEVEL 2 - used at least once every 5 hours
includes
It verifies if an array includes (no kidding!) an elements. It does not work with arrays of objects. You can also specify the start index as a second argument, never used that in my life though.
var hasFive = [1,2,3,4,5].includes(5)
console.log(hasFive) // true
var stuff = ['pasta', 'chicken', 'orange']
var hasPizza = stuff.includes('pizza')
console.log(hasPizza) // false
This is VERY useful when more than one value is acceptable in some if statement.
// use includes:
if(['black','brown','navy blue','deep green'].includes(color)){
console.log('it is dark!')
}
// instead of this:
if(color == 'black' || color == 'brown' || color == 'navy blue' || color == 'deep green') {
console.log('it is dark!')
}
find
Same syntax as filter, but it does not return a complete array, rather the first element of the array that passes the test. If no element passes the test, the return value is undefined
var lunchBaskets = [
{food: 'pizza slices', quantity: 4},
{food: 'pizza slices', quantity: 2},
{food: 'sandwiches', quantity: 2},
{food: 'donuts', quantity: 3}
]
var aLotOfPizza = lunchBaskets.find(b => b.food.includes('pizza') && b.quantity > 2)
console.log(aLotOfPizza) // { food: 'pizza slices', quantity: 4 }
indexOf
In arrays of primitives (numbers, strings, booleans) indexOf returns the index of the searched value.
If there is more than one value that corresponds to the searched value, it will return the first index
var array = ['hatred', 'hatred', 'love', 'hatred', 'love']
var whereIsTheLove = array.indexOf('love')
console.log(whereIsTheLove) // 2
Watch out! It does not work with arrays of objects.
var array = [{name: 'john'}, {name: 'peter'}]
var isTherePeter = array.indexOf({name: 'john'})
console.log(isTherePeter) // -1
// output is going to be ALWAYS -1, even if the array does have an object with 'john' value for the key 'name'
LEVEL 3 - used on a weekly basis
slice
This method returns a subpart of an array, without modifying the array. It’s like substring for strings.
Very simple syntax.
var out = array.slice(A,B)
out array will have the elements of array from index A to index B-1.
You can even not pass the B index as an argument, slice will return all the elements from index A to the end of the array.
var array = [1,2,3,4,5,6,7]
console.log(array.slice(2,5)) // [ 3, 4, 5 ]
console.log(array.slice(2)) // [ 3, 4, 5, 6, 7 ]
trick to take the last element
slice can also receive a negative number as argument (e.g array.slice(-3)).
In this case the output array will have the elements of the original array from index ‘array.lenght -1’ to the end of the array.
Let’s see an example to clarify this thing:
var array = [1,2,3,4,5,6,7]
console.log(array.slice(-3)) // [ 5, 6, 7 ]
You can take advantage of this possibility to take the last element of an array without modifying the array.
var array = [1,2,3,4,5,6,7,8]
var lastElement = array.slice(-1)[0]
console.log(lastElement) // 8
findIndex
This is very similar to indexOf, but you don’t provide an element, rather a callback. The return value of findIndex is the index of the first element that passes the test you pass as argument. Again, the same old syntax as filter, find and others.
var array = ['pizza', 'pasta', 'love', 'money']
var whereIsTheLove = array.indexOf('love')
var whereIsTheLove2 = array.findIndex(el => el == 'love')
console.log('Searched with indexOf: ' + whereIsTheLove) // 'Searched with indexOf: 2'
console.log('Searched with findIndex: ' + whereIsTheLove2) // 'Searched with findIndex: 2'
As for find this is useful when you have an array of objects that cannot be analysed with a simple indexOf or includes.
var array = [{name: 'john'}, {name: 'wally'}, {name: 'peter'}]
var whereIsWally = array.findIndex(el => el.name == 'wally')
console.log('Wally is at index: ' + whereIsWally) // 'Wally is at index: 1'
join
This is kinda different from the others because of its return value which is… a string.
It concatenates all the elements of an array in a single string putting a separator between the elements (no actually need to say that works better with arrays of strings) .
If nothing is specified the default separator is comma (‘,’).
var people = ['John', 'Francine', 'Wally', 'Peter', 'Anna']
var joined = people.join()
var joined2 = people.join(' and ')
console.log('Today there were ' + joined) // 'Today there were John,Francine,Wally,Peter,Anna'
console.log('Today there were ' + joined2) // 'Today there were John and Francine and Wally and Peter and Anna'
If you want to join the strings without any separators just do as the following
var array = ['first','second','third']
var out = array.join('')
console.log(out) // firstsecondthird
If you have an array of objects and you want to join one of the properties of the objects, you’re gonna need to use also a map before the join
var people = [{name: 'John'}, {name: 'Francine'}, {name: 'Peter'}, {name: 'Peter'}, {name: 'Anna'}]
var joined = people.map(el => el.name).join()
console.log('Today there were ' + joined) // 'Today there were John,Francine,Peter,Peter,Anna'
Warning: If an element is undefined, null or an empty array [], it is converted to an empty string.
splice
Splice method is quite powerful. It allows you to remove elements from an array (permanently) and at the same time to add new elements.
Both operations are optional.
It returns an array containing the deleted elements.
Warning: it obviously modifies directly the array.
First, let’s analyse the syntax: splice(startIndex, deleteCount, item1, item2, … , itemN)
startIndex = where to start deleting and/or inserting
deleteCount = how many elements to delete starting from startIndex, can be 0.
Item1, … , itemN = the items to optionally insert.
Let’s see three basic examples that will certainly clarify how it works
// DELETE 2 ELEMENTS
var array1 = [1,2,3,4,5]
var out = array1.splice(1,2)
console.log(array1) // [ 1, 4, 5 ]
console.log(out) // [2,3]
// INSERT 2 ELEMENTS
var array2 = ['pizza', 'pasta', 'chicken']
array2.splice(2, 0, 'sandwich', 'cake')
console.log(array2) // [ 'pizza', 'pasta', 'sandwich', 'cake', 'chicken' ]
// REPLACE 1 ELEMENT WITH NEW STUFF
var array3 = [1,2,3,4,5]
array3.splice(2, 1, '*', '*', '*')
console.log(array3) // [ 1, 2, '*', '*', '*', 4, 5 ]
And with these methods you are already well placed in almost all cases.
However, let’s see other methods that happen to be used less often, but with which you can start feeling like an almost-senior-developer and to be in the position of asking your boss for a promotion.
LEVEL 4 - used once every 2 months maybe?
shift
Takes off and returns the first element (index 0) of the array.
It’s pretty much equivalent to splice at index 0, but shift returns the element, not an array.
Shift is much faster than splice, but… you know, one more method to learn.
var array1 = [1,2,3,4]
var array2 = [1,2,3,4]
var out1 = array1.shift()
var out2 = array2.splice(0,1)
console.log(out1) // 1
console.log(out2) // [ 1 ]
console.log(array1) // [ 2, 3, 4 ]
console.log(array2) // [ 2, 3, 4 ]
sort
It allows you to sort (again, no kidding!) the elements of an array. The problem is that it’s not intuitive at all. For basic sorting you’re gonna end up knowing by heart its syntax, for more complex cases you might wanna look up on the internet how to do it.
sort method seems like a big deal but you don’t really need to sort arrays a lot, a least in my experience. You normally put data into tables or charts (from third part libraries) and they all come with built-it sorting features or they automatically sort data for you. Or, data that should be sorted, come from some SQL or noSQL query, and you already put the sort direction in the query.
Anyway… the syntax is apparently simple:
array.sort()
This line of code sorts the elements of the array in alphabetical and ascending order (so the array is modified after sort is called).
It compares the sequences of UTF-16 code units values of the elements to make the sorting.
var array = ['blue', 'pizza','zebra', 'john', 'friends', 'anime']
array.sort()
console.log(array) // [ 'anime', 'blue', 'friends', 'john', 'pizza', 'zebra' ]
WARNING: it is an alphabetical order, so you cannot use a simple sort() to order numbers.
var array = [1,3,7,211,5,4]
array.sort()
console.log(array) // [ 1, 211, 3, 4, 5, 7 ]
BUT, you can specify a compare function as optional parameter, and it allows you to perform more complex sortings.
sort((a, b) => { /* ... */ } )
// Compare function
sort(compareFn)
// Inline compare function
sort(function compareFn(a, b) { /* ... */ })
So the sorting is based on the compareFunction return value. In this function a and b represents two whatever elements of the array.
How does the compare function work? Something like this:
- Return value is > 0: b goes before a
- Return value is < 0: a goes before b
- Return value is == 0: a and b take their original order
To explain this better let’s see two example.
The first is to order arrays of numbers, and this is the case you’re gonna end up using sort the 95% of the times:
var array = [1,3,7,211,5,4]
// ascending order
array.sort((a,b) => a-b) // [ 1, 3, 4, 5, 7, 211 ]
// descending order
array.sort((a,b) => b-a) // [ 211, 7, 5, 4, 3, 1 ]
And a version with an array of objects
var array = [{name: 'john', score: 4}, {name: 'peter', score: 12}, {name: 'walter', score: 110}, {name: 'michael', score: 12}, {name: 'frank', score: 1}]
array.sort((a,b) => {
if(a.score > b.score){
return -1
}
if(a.score < b.score){
return 1
}
if(a.score == b.score){
return 0
}
})
var whoIsTheBest = array.map(a => a.name)[0]
console.log(whoIsTheBest)
I usually get the sorting direction wrong at the first try. Damn it!
pop
When applied to an array pop takes off the last element and returns it (it modifies the array).
If your objective is to just remove the last element It’s obviously equivalent to array.splice(array.length-1, 1)
It's very convenient when you have a string that represents a file path and you want to extract the file extension from it.
var path = '/some.tricky/path/to.some.file_1.txt'
var extension = path.split('.').pop()
console.log(extension) // 'txt'
This can be achieved also using the slice(-1) trick. They are slightly different though because slice does not modify the array.
var array1 = [1,2,3,4,5]
var array2 = [1,2,3,4,5]
var out1 = array1.pop()
var out2 = array2.slice(-1)[0]
console.log('out1: ' + out1) // 5
console.log('out1: ' + out2) // 5
console.log(array1) // ['1,2,3,4']
console.log(array2) // [1,2,3,4,5']
So it’s completely replaceable by splice/slice, but it’s a handy shortcut.
BONUS LEVEL: Nice to know methods which you can easily survive without, but hey they are so cool.
some / every
At least one / every element of the array passes the test you provide as callback. I put them here just because it happened to me to use them some days ago and I remembered they exist. Just in!
var pizzas = ['pizza', 'pizza', 'pizza', 'pizza']
var areTheyReallyAllPizzas = pizzas.every(p => p == 'pizza')
console.log(areTheyReallyAllPizzas) // true
var mixedFood = ['pasta', 'pizza', 'chicken', 'pizza']
var isThereAtLeastOnePizza = mixedFood.some(f => f == 'pizza')
console.log(isThereAtLeastOnePizza) // true
same thing without some/every - be creative with what you know!
// EVERY
var pizzas = ['pizza', 'pizza', 'not pizza', 'pizza']
var areTheyReallyAllPizzas = true
pizzas.forEach(p => {
if(p != 'pizza'){
areTheyReallyAllPizzas = false
}
})
console.log(areTheyReallyAllPizzas) // false
// OR
areTheyReallyAllPizzas = pizzas.filter(p => p !='pizza').length == 0
console.log(areTheyReallyAllPizzas) // false
// SOME
var mixedFood = ['pasta', 'pizza', 'chicken', 'pizza']
var areThereAtLeastOnePizza = mixedFood.filter(p => p == 'pizza').length > 0
console.log(areThereAtLeastOnePizza) // true
unshift
It adds one or more elements (works exactly like push) at the beginning of the array.
With (not so) modern (anymore) javascript it can be easily replaced with the ...
operator.
Since I guess that you’re gonna see three dots everywhere when you look for something on stack overflow in these days, I believe you’re never gonna use unshift.
var array1 = [1,2,3]
var array2 = [1,2,3]
array1.unshift(3,2,1,0)
console.log(array1) // [ 3, 2, 1, 0, 1, 2, 3 ]
array2 = [...[3,2,1,0], ...array2]
console.log(array2) // [ 3, 2, 1, 0, 1, 2, 3 ]
reduce
reduce is very powerful, yet so little intuitive.
You want to use it when you need an output that depends on all the elements in an array in succession.
If you really cannot remember how to use reduce you can always use a for or forEach loop after having set an accumulation variabile outside the loop.
The callback takes 3 arguments: the first is the accumulator value (where the partial value in stored at every step), the second is the current element, the third is the index value (optional).
In the following example you see how to sum all the elements of a value but the element at index 0, starting with a value of 5.
var array = [1,2,3,4,5]
var out = array.reduce((acc,current,index) => {
if(i != 0){
return acc + current
} else{
return acc
}
}, 5)
console.log(out) // 19
reduceRight does the same thing starting from last index.
Listen to me, when you start learning array methods you don’t need reduce at all, yet it is so nice to show off your code and make other people think that you’re a Javascript Badass.
here it is an example on how to cope without reduce
// sum all the elements in an array starting from 3
var out = array.reduce((a,b) => a+b, 3)
// Is equivalent to
var out2 = 3
array.forEach(e => out2+=e)
Not that more complex, isn’t it?
And that’s pretty much it… I’m not saying that you don’t have to delve more deeply into the other methods or loops or ninja tricks, I’m just saying that in the past 5 years I used them just a very little number of times and I still have my job.
Posted on April 25, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.