The Arrays Cheat Sheet I Wish I Had
An understanding of Arrays is so critically important in the early days of learning JavaScript. They’re used constantly and in ways that only get more complicated as you learn and grow your skillset. So why, if I used them so often, did I have such a hard time remembering any of the most common array tools? It was hard enough just to remember their names, let alone how they work. If only there was a one-stop shop of the tools I needed to use most frequently with plain English explanations of how to use them…
Disclaimer: I’m still learning! Accordingly, this will contain vastly oversimplified explanations intended just to provide quick references and reminders of available options. For more thorough and accurate details, I strongly recommend reading the fantastic documentation on MDN.
.map()
What it does: Change all elements and give you a new array.
This is great when you would like to change each of the elements in an array into something new, leaving you with a new array that will be the same length as the original.
Example:
const initialArray = ["a", "b", "c"]
const arrayAfterMap = initialArray.map(eachElement => eachElement.toUpperCase())
// arrayAfterMap = ["A", "B", "C"]
In this example, each element is run through this function that converts the string to uppercase letters. This is a fairly simple change, but .map() is pretty powerful, particularly when dealing with arrays of objects. Individual key/value pairs can be targeted within an object, providing a lot of flexibility for what map will let you change.
.filter()
What it does: Remove all elements that don’t meet a certain condition.
This works exactly as the name implies- it will filter out any elements that don’t meet a certain condition and leave you with an array of elements that do meet that condition.
Example:
const initialArray = ["a", "b", "c"]
const arrayAfterMap = initialArray.filter(eachElement => eachElement !== "b")
// arrayAfterMap = ["a", "c"]
In this example, the filter is checking to see if each element is not “b”. If everything after the arrow is true for the given element, that element will be in your new array.
.forEach()
What it does: Pass every element through a function.
It sounds similar to .map() at first, but the critical difference is .map() will give you a new array, while .forEach() will not by default. This won’t return anything on its own (specifically, it returns undefined), but the given function within .forEach() will return whatever it is intended to return.
Example:
const initialArray = ["a", "b", "c"]
initialArray.forEach(eachElement => console.log(eachElement+"x"))
// Console will display:
// "ax"
// "bx"
// "cx"
In this example, each element is passed through a function that does two things: it will attach “x” to the end of the element string and it will log the new string to the console.
.pop() vs .push() vs .shift() vs .unshift()
What they do: Add/remove an element to/from the beginning/end of an array.
I’ve grouped these together because they all behave similarly, but it can be difficult to remember which one to use. I found this blog by Yaphi Berhanu to provide a few helpful tips for remembering the differences.
A barebones breakdown of each is:
.pop() removes the last element of an array
.push() adds an element to the end of an array
.shift() removes the first element of an array
.unshift() adds an element to the beginning of an array
Example:
const initialArray = ["a", "b", "c"]
initialArray.pop() // initialArray = ["a", "b"]
initialArray.push("c") // initialArray = ["a", "b", "c"]
initialArray.shift() // initialArray = ["b", "c"]
initialArray.unshift("a") //initialArray = ["a", "b", "c"]
It is important to note here that each of these methods will change your initial array. We do not end up with a new array in these cases, rather our initial array was changed at each individual step.
“…” aka the Spread Operator
What it does: Separate out each element of an array while also creating a separate copy of those elements.
There are some subtle distinctions with the spread operator that I’m still wrapping my head around, so let’s break this down:
Separate out each element of an array…
If you were to make reference to a variable which contains an array without using the spread operator, you’re referencing the entire array. Effectively, everything within the brackets as well as the brackets themselves.
If, however, you reference that variable with the spread operator, you are in a sense taking away those outer brackets and looking at each individual element as its own entity. In effect, spreading the array out into its component parts.
…while also creating a separate copy of those elements.
Again, if you were to refer to a variable which contains an array without using the spread operator, you’re referencing that original array, not making a new copy of it. If that initial array were to change, your reference to it later will also be changed.
If you use the spread operator, you’re effectively creating “new” data. If the original array were to change, your “new” data will not be changed.
Example:
const initialArray = [1,2,3]
const newArray = ["a", initialArray, "b"]
const spreadArray = ["a", ...initialArray, "b"]
console.log(initialArray) // [1, 2, 3]
console.log(newArray) // ["a", [1, 2, 3], "b"]
console.log(spreadArray) // ["a", 1, 2, 3, "b"]
initialArray.pop() // removes the "3" from our initial array
console.log(initialArray) // [1, 2]
console.log(newArray) // ["a", [1, 2], "b"]
console.log(spreadArray) // ["a", 1, 2, 3, "b"]
In this example, newArray does not use the spread operator. As a result, in the first set of console logs, we end up with an array inside of an array. Then, after initialArray is altered by .pop(), we see in the second set of console logs that newArray is now also missing the number 3, even though we didn’t directly change the contents of newArray.
In contrast, spreadArray is created via the spread operator. Accordingly, in the first set of console logs, we see that we have one simple array that doesn’t contain any inner arrays because the contents of initialArray were “spread” out as individual elements. We also see in the second set of console logs that spreadArray was not at all affected by the changes that took place with the initialArray because the spread operator isn’t simply referencing initialArray, it is creating a copy of its individual elements.