Better Programming

Advice for programmers.

Follow publication

5 JavaScript Array Methods and the Gotchas That You Should Watch Out For

Learn the intricacies of map, reduce, sort, foreach, and more

Mickey
Better Programming
Published in
9 min readApr 18, 2021

--

Laptop on the ground
Photo by Blake Connally on Unsplash.

We’ve all been there: we’re in that coding flow where code springs from our fingers like lightning bolts. Then we need a method to manipulate an array, but we’re blanking! So we do some quick Googling, even quicker copy-pasting, run our code, and there it is: a big red error in our console. All because our code was slightly different from the code we copy-pasted.

This article aims to prevent that from happening again by improving your understanding of five commonly used array methods, their ins and outs (complete with example use cases), and the gotchas to watch out for! Whether you recently started coding or you’ve been doing it for a couple of years, these tips and tricks include both easy-to-understand examples as well as advanced use cases.

These are the five array methods (sorted) to learn by heart that will take your coding skills to the next level!

Red background with yellow word reading “FILTER”

Filter

  • Returns a new array.
  • Does not mutate the array on which it is called.

This one is pretty self-explanatory and won’t require any memory techniques to remember. Want to filter your array? Go ahead and use the filter method! The filter method iterates over each element in the array and returns only the items that pass the test implemented by the provided function.

The filter method accepts three arguments:

  1. the currentValue of the element
  2. the index of the element in the array
  3. the array itself

Usage

let oldBand = ["Scary", "Baby", "Ginger", "Sporty", "Posh"]let newBand = oldBand.filter(currentElement => currentElement.length > 4)console.log(newBand)
// Outputs: Array ["Scary", "Ginger", "Sporty"]

In our example above, we use the filter method on our oldBand variable to create a newBand variable where we only keep the band members with a name longer than four letters.

A typical use case for the filter method is to allow your user to filter articles on a news site, posts on a blog, or users on a social platform. In a situation where we want to allow our users to filter through an array of articles, our code might look like this:

We define a searchTerm variable (which would typically be bound to a text input) and point it to “React” (i.e. we only want to find articles that have “React” in their title). We’ve then bound a variable, articles, to an array of articles (typically fetched from a database). Finally, we create a new array with help from the filter method and pass it a function that utilises the includes method to look for our searchTerm within the titles of our objects contained in our articles array. The includes method differentiates between uppercase and lowercase letters. Thus, we need to alter our strings in our passed function with the help of the toLowerCase method.

Gotchas

This one doesn’t really have any gotchas other than that a function has to be provided (i.e. only calling array.filter() without calling a function will throw a TypeError).

Yellow background with black word reading “FOREACH”

forEach

  • Returns nothing, but executes the provided function for each element in the array.
  • Does not mutate the array on which it is called.

This one is also pretty obvious — it will execute the function we provide once for each element in the array. However, the forEach method should only be used if there are no better tools for the job.

At first glance, it may just look like an innocent, simplified for loop, but it’s important to remember that methods are not loops and this bad boy has some nasty gotchas if you don’t think before you code! The forEach method takes a function and executes the function for each element in the array.

The forEach method accepts three arguments:

  1. the currentValue of the element
  2. the index of the element in the array
  3. the array itself

Usage

let fruits = ["apple", "banana", "lemon"]fruits.forEach(element => console.log(element))
// Outputs: "apple"
// Outputs: "banana"
// Outputs: "lemon"

Our example above simply logs each value in the array to our console. As you probably can tell, forEach is a generic tool to use when no better option is available.

Even though forEach itself doesn’t mutate the array upon which it is called, we are allowed to mutate the array via the provided function, though the best practice is to use a method that suits the purpose (e.g. the filter or map method). To give you an idea of how we can achieve array manipulation with forEach, and also why it should be avoided, have a look at the code below:

let countDown = [4, 3, 2, 1, 0]countDown.forEach((element, index, array)=> {
element > 1 ? array.splice(index, 1) : ""
})
console.log(countDown)
// Outputs: [3, 1, 0]

Writing the above, we expect our function to remove all elements with a value higher than 1. Since we’re manipulating the array during iteration, what actually happens is that the function only runs on every other index because as we remove elements before the iteration has ended, our array keeps shrinking. It becomes clear when logging the element and index from within our forEach function, like so:

Gotchas

You wouldn’t think that a basic function like this would have any gotchas, but we’ve already covered one above! Another gotcha that is easily overlooked is if there’s an empty or undefined index within the array that the forEach method is called on (i.e. myArr = [1, 2, , 4, 5]), the function will not be called on the empty index (myArr[2] in this case).

Eventually, we will run into situations where we will need to work with external references such as a database, which in turn requires us to work asynchronously.

A drawback of the forEach method is that it expects a synchronous function and will not wait for promises. Thus, if we need to traverse an array within a function that is already running asynchronously, we lose control of the execution order of asynchronous functions. In those situations, it is better to use a for...of block, which is a loop and not a function, and as such doesn’t have to be executed asynchronously in itself.

Green background with black word reading “MAP”

Map

  • Returns a new array.
  • Does not mutate the array on which it is called.

The map method takes a function and returns a new array populated with the results of the provided function. This could be the first method new developers encounter since it’s the method to use when building collections of elements in React, for example. Remembering the name of it might be a bit trickier since the name doesn’t really describe what it does.

In mathematics, map and function are used interchangeably, which might make this one easier to remember if you’re a mathematician. Try to think of the active verb though, mapping. We’re mapping each element in our old array to our new array.

The map method accepts three arguments:

  1. the currentValue of the element
  2. the index of the element in the array
  3. the array itself

Usage

let oldSalaries = [3000, 1500, 7000]newSalaries = oldSalaries.map((element) => element * 1.02)console.log(newSalaries)
// Outputs: Array [3060, 1530, 7140]

The code above shows a simple example of how to use the map method. We have a list of salaries that are due for yearly renewal. We map over our old array, give everyone a raise of 2%, and save it in our newSalaries variable.

A typical use case for the map method is when we have an array and we want to create a new array based on the values contained in our initial array. If you’ve been doing some coding in React, you may well have used this without thinking about it when embedding inline JSX and traversing data stored in an array to create UI components:

Gotchas

Just like with the forEach method, map will not iterate over empty indexes or indexes that are undefined in our array. Although it’s possible to manipulate the source array and disregard the returned array, this is an anti-pattern. In such cases, forEach or a for...of block should be used instead.

Another thing map has in common with forEach is that it can cause unforeseen issues when manipulating the source array during iteration. This shouldn’t be a big issue, though, seeing as map already returns a new array.

Blue background with white word reading “REDUCE”

Reduce

  • The return depends on what function is implemented and what is provided as the initialValue.
  • Always provide an initialValue to avoid the gotchas!
  • Does not mutate the array on which it is called.

The trick to remembering reduce is to think of it as a method reducing your array to one new variable — be it a number, string, array, or something else. In its simplest form, it will reduce your array consisting of numbers to one number, but it has more uses than that!

The reduce method accepts four arguments:

  1. the accumulator
  2. the currentValue of the element
  3. the index of the element in the array
  4. the array itself

Usage

Use cases may seem limited to only working with numbers at first, but there are other situations where the reduce method can prove beneficial (e.g. when grouping objects stored in an array by property).

Gotchas

If the array is empty and no initialValue is provided, a TypeError will be thrown. If the array only has one element (regardless of position) and no initialValue is provided — or if an initialValue is provided, but the array is empty — the solo value will be returned without calling the provided function.

Purple background with yellow word reading “SORT”

Sort

  • Returns the same array.
  • Can be called in place (i.e. array.sort()).
  • Mutates the array on which it is called by sorting it.

This one does what it says it does: it sorts our array. However, we should always provide a compare function to avoid the gotchas. If no function is provided, the sort method will convert every element into strings, compare their sequences of UTF-16 code unit values, and sort them in ascending order. Thus “angular” comes before “bootstrap”, and because of the conversion to strings, 700 comes before 9.

The sort method accepts two arguments:

  1. the firstElement for comparison
  2. the secondElement for comparison

When provided with a compare function, this is how sort will interpret the returned value:

  • if the provided function returns less than 0, leave firstElement and secondElement unchanged.
  • if the provided function returns 0, leave firstElement and secondElement unchanged with respect to each other but sorted with respect to all different elements.
  • if the provided function returns greater than 0, sort secondElement before firstElement.

Usage

let numbersArray = [46, 2000, 12, 58, 300]numbersArray.sort((a, b) => a - b)console.log(numbersArray)
// Outputs: [12, 46, 58, 300, 2000]

The example above shows a simple compare function for sorting an array containing numbers in ascending order.

With a slight tweak, a similar compare function can be used to sort dates:

Finally, if we have an array containing a mix of capitalised and lowercase strings, we could sort it alphabetically like this:

Gotchas

Always provide a compare function to control the output. Remember how if we don’t provide a compare function, the sort method will convert elements into strings and compare them? This causes capitalised words to come before lowercase words (i.e. “Bootstrap” comes before “angular”), which is easy to forget and may therefore cause issues down the line.

If there are values that are undefined in our provided array, they will be sorted to the end of the array. As such, you should always provide sort with an array consisting of the same primitive values or objects.

Conclusion

That concludes our list of array methods to learn by heart to make you more successful and efficient in your coding! Thanks for taking the time to read to the end of this article. I hope you learned something new!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response