logo image Faisal Rahman
ID EN
My profile picture taken in the summer Faisal Rahman

Arrays Can Do That?


Arrays in JavaScript are a fascinating thing. Not only because they can store elements of any data type — even undefined — but also because Arrays have many interesting methods on their prototype that can be used in a variety of situations. These methods are attached to the Array object’s prototype so they can be used directly after the Array literal notation, like [].indexOf() for example.

These methods attached to the Array prototype are called, take a guess… yes, that’s right, Array prototype methods. If you write JavaScript programs day-to-day, you’ve likely come across some of these methods, such as map, filter, reduce, or find. But did you know that there are far more Array prototype methods than those? Let’s explore some interesting ones that are relatively rarely encountered in everyday work.

Unshift

You may already be familiar with push, which adds a new element to an Array. unshift also adds an element to an Array. The difference is that while push adds a new element at the end, unshift adds a new element at the beginning of the Array.

const arr = [1, 2, 3];
arr.unshift(4); // 4
console.log(arr); // [4, 1, 2, 3]

One use case for the unshift method is building a first-in first-out (FIFO) queue Array by combining it with pop.

const queue = [];
queue.unshift(1);
queue.unshift(2);
queue.unshift(3);

const item = queue.pop(); // 1

console.log(queue); // [3, 2]

Shift

There’s unshift, and there’s also shift. If unshift is used to add elements, shift is used to remove elements like pop, except shift removes the first element of an Array while pop removes the last.

const arr = [1, 2, 3, 4, 5];
const firstEl = arr.shift(); // 1

console.log(arr); // [2, 3, 4, 5]

You could say the unshift-shift duo is the counterpart of push-pop, operating in the opposite direction.

Includes

Checking for the presence of an element in an Array is a very common use case. Before ES6, the way to do it was with the indexOf method, which returns the index of the searched element, or -1 if the element is not found.

["a", "b", "c", "d"].indexOf("b") > -1; // true

ES6 introduced a new, more readable way to check for an element’s presence in an Array: includes, which returns true if the element is found in the Array.

["a", "b", "c", "d", "e"].includes("b"); // true

There are some differences between the indexOf and includes methods, including:

Searching for NaN

The indexOf method performs comparisons using strict equality, and in JavaScript NaN !== NaN, so indexOf will never find a NaN value. On the other hand, includes can find NaN.

const arr = [NaN, 0, 1, 2];

arr.indexOf(NaN) > -1; // false
arr.includes(NaN); // true

Searching for empty slots

Arrays in JavaScript can have empty slots — not undefined or null, but truly empty with no value whatsoever. There are several ways to create an Array with empty slots, such as using the Array constructor (new Array(5)), extending an Array’s length beyond its current elements ([1, 2, 3].length = 5), or omitting elements at initialization ([,,,]).

The indexOf method will skip empty slots in an Array, so we can’t find them with indexOf. However, the includes method treats empty slots as undefined, so we can find them by passing undefined as the parameter.

const arr = [, , , ,];

arr.indexOf(); // -1
arr.indexOf(undefined); // -1

arr.includes(); // true
arr.includes(undefined); // true

Find Index

Arrays have a findIndex method. At a glance, it looks similar to indexOf, right? Both methods return the same type of output: the index of the element being searched for.

The difference is that while indexOf accepts a value as its parameter, findIndex accepts a function. Both indexOf and findIndex return the index of the first element from the beginning of the Array that matches the search criteria.

The findIndex method returns the index of an element when the callback function we provide returns a truthy value for that element.

const members = [
  { name: "Sowon", position: "leader" },
  { name: "Yerin", position: "dancer" },
  { name: "Eunha", position: "vocal" },
  { name: "Yuju", position: "vocal" },
  { name: "SinB", position: "dancer" },
  { name: "Umji", position: "maknae" },
];

const searchFn = (member) => member.position === "vocal";

members.findIndex(searchFn); // 2

The search function can have three parameters, which in order are:

Last Index Of

Still on the topic of indexes, in addition to indexOf, Arrays also have lastIndexOf. The lastIndexOf method is identical to indexOf in every way, except for its search direction: lastIndexOf searches for the element’s index starting from the last element back to the first.

const arr = ["a", "b", "b", "a"];

arr.indexOf("b"); // 1
arr.lastIndexOf("b"); // 2

Like indexOf, lastIndexOf also accepts a second Number parameter that specifies the starting index for the search. This starting index is inclusive, so if the searched element is found at the starting index, that starting index will be returned.

const arr = ["a", "b", "b", "a"];

arr.indexOf("b", 2); // 2
arr.lastIndexOf("b", 1); // 1

Some & Every

We’ve met the includes method for checking element presence in an Array. Besides includes, there are also the some and every methods that check for element presence. The fundamental difference between some and every versus includes is that some and every accept a function as their search parameter, while includes accepts a value.

The difference between some and every themselves is that some returns true when the search function returns a truthy value for at least one element in the Array, while every only returns true when the same happens for every element in the Array.

const arr = [1, 2, 3, 4, 5];

arr.some((el) => el > 3); // true
arr.every((el) => el > 3); // false

As you might guess, the some method will exit immediately when the search function returns true, while every will evaluate the Array to the end because it must verify that all values meet the criteria.

The search function accepted by some and every has the same specification as the findIndex search function: three parameters — the element, the index, and a reference to the Array.

Reduce Right

One of the most popular Array Prototype Methods is reduce. But did you know that reduce has a sibling, reduceRight, which performs the reduce operation from the end to the beginning of the Array? Aside from its direction, reduceRight has specifications identical to reduce.

// Returns 'noon'
["n", "o", "o", "n"].reduce((accumulator, current) => accumulator + current);

// Returns 'noon'... wait, this isn't a great example
["n", "o", "o", "n"].reduceRight(
  (accumulator, current) => accumulator + current,
);

// Sorry about that, here's a proper example hehe =====================

// Returns 'abc'
["a", "b", "c"].reduce((accumulator, current) => accumulator + current);

// Returns 'cba'
["a", "b", "c"].reduceRight((accumulator, current) => accumulator + current);

Beyond these methods, there are many more methods that Arrays have on their prototype. Feel free to visit the MDN documentation to see a more complete list. Three methods were intentionally omitted here — map, filter, and reduce — because I feel they deserve their own dedicated article.

References
Array - Javascript | MDN
Difference Between indexOf and findIndex function of array | StackOverflow