Working with arrays in JavaScript

Here are some helpful tips and tricks related to arrays in JavaScript

By: Ajdin Imsirovic 02 December 2019

This is an ultimate article on arrays in JavaScript. We’ll go in depth of this data structure in JS, and understand a number of different use cases, tips, tricks, and techniques.

Some useful tips and tricks in JavaScript Image by CodingExercises

Using the delete method on an array member

If you use the delete method on an array member, this doesn’t erase the value, it just replaces it with undefined:

var arr = ['one','two','three','four'];
delete arr[0];
console.log(arr); // returns: [undefined, 'two', 'three', 'four']

Does a value exist in an array?

We check using the indexOf method:

var arr = ['one','two','three','four'];
arr.indexOf('five'); // returns: -1
arr.indexOf('four'); // returns: 3

When it returns -1, it means it can’t find the specified member in the array.

Alternatively, the includes method returns true if a matching member is found, and false otherwise:

['one','two','three','four'].includes('one'); // returns: true
['one','two','three','four'].includes('five'); // returns: false

You can pass another argument to includes to specify which member of array to start to search from:

['one','two','three','four'].includes('two', 1); // returns: true
['one','two','three','four'].includes('two', 2); // returns: false

Use Array.length to find the last member of array

Since Array.length counts an array from 1, and arrays are zero-indexed, it’s easy to get the last member of an array:

arr[arr.length - 1]; // returns: "four"

Use Array.length to quickly trim an array

You can change the length of an array on the fly, using Array.length property, like this:

arr.length = 2;
console.log(arr); // returns: [undefined, "two"];

Manipulating arrays with pop

The pop() method is used to remove an item from an array. For example, on Google search results, we can get the all the h3 search results’ headings into an array like this:

var arr = [...document.getElementsByTagName('h3')];
arr.length;
arr.pop();

On the second row in the above code, we check the length of the array.

On the third row, we removed a member that was placed in the last position of arr array.

On the fourth row in the above code, we check the length of the array again - now its’ length is smaller by one.

Manipulating arrays with push

The push method is the opposite of pop:

var arr = [];
arr.push('one');
arr.pop;

Manipulating arrays with shift

The shift method is like pop, only it removes items from the start, not the end:

var arr = ['one','two','three','four'];
arr.shift();
arr; // returns: ['two','three','four']

Manipulating arrays with unshift

The unshift method is like push, only it adds items from the start, not the end:

var arr = ['one','two','three','four'];
arr.shift();
arr.unshift('one');
arr; // returns: ['one','two','three','four']

Manipulating arrays with Array.slice and Array.splice

The slice method returns a specified slice of the source array.

For example, we want to extract only the last two items from the below array:

var arr = ['one','two','three','four'];
arr.slice(2,3); // returns: ['three']
arr.slice(2); // returns: ['tree','four']
arr.slice(2,4); // returns: ['tree','four']

The Array.slice method is non-destructive.

The splice method does two things:

  1. It removes specified items from an array
  2. It optionally puts new items in the removed slots

An example of removing the first entry in an array:

var arr = ['one', 'two', 'three', 'four'];
arr.splice(0,1); // returns: ['one']
arr; // returns: ['two','three','four']

The first argument to the splice method specifies where to start splicing. The second argument specifies how many items to splice. The remaining arguments represent the optionaly new items to add in the place of removed slots.

Note that slice is non-destructive, and splice is destructive.

Destructuring Arrays

We can group multiple values in an array.

Thus, instead of writing:

var one = 'one';
var two = 'two';
var three = 'three';
var four = 'four';

…we can write:

var arr = ['one','two','three','four'];

But what if we want to go the other way round? To take members of array and make each of them individual variables?

That’s where array destructuring comes in:

var [one,two,three,four] = arr;

Now the variables are available individually:

console.log(one); // returns: "one"

You can also skip values, like this:

var [_1, , ,_4] = arr;
_1; // returns: "one"
_2; // returns: Uncaught ReferenceError: _2 is not defined at <anonymous>:1:1
_4; // returns: "four"

You can use the rest operator, ..., to get back a sub-array:

var [_one, ...others] = arr;
console.log(_one); // returns: "one"
console.log(others); // returns: ['two','three','four']

Concat two arrays together

Let’s say we’ve got these two arrays:

var arr1 = ['one'];
var arr2 = ['two'];

We can combine them like this:

arr1.concat(arr2); // returns: ['one','two']

…but if we do this:

arr1; // returns: ['one']

Obviously, the concat method doesn’t update arr1. It’s an easy enough fix though:

arr1 = arr1.concat(arr2);

We can also concat two arrays using the spread operator ..., like this:

var _arr1 = ['one','two'];
var _arr2 = ['three','four'];
var _arr1 = [ ..._arr1, ..._arr2 ];
_arr1; // returns: ['one','two','three','four']

Convert an array to a string

We can do this with the help of the join method.

var arr = ['one','two','three','four'];
arr.join(); // returns: "one,two,three,four"

If you’re a musician, you might wanna return this:

arr.join(' and '); // returns: "one and two and three and four"

Flipping the order of items in an array

The destructive reverse method makes this possible:

var arr = ['one','two','three','four'];
arr.reverse(); // returns: ['four','three','two','one']

Sorting arrays with Array.sort

It’s simple:

var arr = ['one','two','three','four'];
arr.sort(); // returns: ['four','one','three','two']

It’s also a destructive method.

There can be some unexpected behavior: capital letters are sorted before small letters:

var arr = ['one','One','two','Two'];
arr.sort(); // returns: ['One','Two','one','two']

Additionally, numbers are sorted based on the first digit in each item:

[300,20,1].sort(); // returns: [1,20,300]
[100,20,3].sort(); // returns: [100,20,3]

Thus, the sort method, out of the box, is probably not the best tool to use.

However, it can still be used in certain situations, as long as we’re aware of its limitations. Sometimes, that simply means that we need to overcome the limitations of the sort function, by passing it a callback function to deal with the fact that it doesn’t sort numbers the way we’d expect.

How do we “fix” the sort function? We’ll start off with defining a new function declaration that we’ll call compareNums:

function compareNums(nextNum, prevNum) {
    return nextNum - prevNum;
}

The compareNums method compares two numbers:

  • if the nextNum number is larger than the prevNum, it returns a positive value
  • if the nextNum number is the same as the prevNum, it returns a 0
  • if the nextNum number is smaller than the prevNum, it returns a negative value

Next, we’ll pass the compareNums function as a callback to the sort function, like this:

[100,20,3].sort(compareNums); // returns: [3,20,100]

To see the inner workings of our little sorting program, we can re-write it like this:

debugger;
function compareNums(next, previous) {
    console.log(`${next} - ${previous}`);
    return next - previous
}
[100,20,3].sort(compareNums);

Running the above code will return the same result as the previous one, except this time we’ll also see some output in the console:

20 - 100
3 - 20

Now we can think things through a bit better. The sort method runs the compareNums function. The first time it’s run, it looks like this:

compareNums(20, 100) {
    console.log(20 - 100);
    return 20 - 100
}

So, it returns -80. The next time it’s run, it looks like this:

compareNums(3, 20) {
    console.log(3 - 20);
    return 3 - 20
}

So, it returns -17.

The final output that’s returned from running all of the above code is:

[3,20,100]

It’s important to note that both times the compareNums was ran, we got back negative numbers: the first time around, it was -80, the next time around, it was -17. The point is, both times it was ran, the returned result was a negative number.

Why does this work?

If we look at the definition of the sort function, we’ll find that it reads like this:

arr.sort([compareFunction])

The compare function is entirely optional. If we don’t provide it to the sort function, each member of the array will be coerced to string, then sorted. However, if we do provide the callback function, we need to give our callback function two params (in our example, the nextNum and the prevNum).

The way that the numbers are compared, works like this:

  1. If nextNum minus previousNum returns less than zero, the nextNum comes first
  2. If the result returned is zero, both numbers are not moved in respect to one another, but they are moved in relation to all other elements.
  3. If nextNum minus previousNum returns more than zero, the nextNum comes second

Now we can improve our compareNums function, like this:

function compareNums(next, previous) {
    if (next < previous) {
        console.log(`${next} is less than ${previous}, so ${next} comes first`);
        return -1
    }
    if (next > previous) {
        console.log(`${next} is greater than ${previous}, so ${next} comes second`);
        return 1
    }
    console.log(`${next} is equal to ${previous} so we are not moving them`);
    return 0;
}
[100,20,3].sort(compareNums);

One additional thing to note: The array is sorted in place - meaning, it uses no auxiliary data structure. Also, the sort method doesn’t make a copy of the array it’s working on.

Next, we’ll see an example of solving a simple problem with arrays and some array methods, including sort.

Exercise: Sort a todo list

Let’s say you have the following text in a txt file:

1. take out trash
3. learn js
2. go shopping
5. have some rest
4. watch a movie

How do you organize the above text using JavaScript, so that it’s ordered by numbers?

Here’s the solution.

First, we add the text:

var todos = `1. take out trash
3. learn js
2. go shopping
5. have some rest
4. watch a movie`;

Next, we replace the newline characters with a character that doesn’t exist in the string, then we split the string using the “weird” character.

todos = todos.replace( /\n/g, "|" ).split( "|" )

Next, we’ll use sort:

todos = todos.sort();

That’s it, we get the result we wanted:

["1. take out trash", "2. go shopping", "3. learn js", "4. watch a movie", "5. have some rest"]

Additional Exercise: Reverse the order of array

To make the order of todos descend rather than ascend, we can use the reverse method:

todos = todos.reverse()
// returns: (5) ["5. have some rest", "4. watch a movie", "3. learn js", "2. go shopping", "1. take out trash"]

We can revert the array back to string:

todos = todos.join(",")
// "4. watch a movie,5. have some rest,2. go shopping,3. learn js,1. take out trash"

And now we can add a space after the , character:

todos.replace(",", ", ")
// returns: "5. have some rest, 4. watch a movie,3. learn js,2. go shopping,1. take out trash"

Looping over arrays

We can loop over arrays in a various number of ways.

I’ve collected 15 ways to do it, divided into two categories:

  1. “Traditional” methods of looping over arrays in JS
  2. Functional methods of looping over arrays in JS

Here’s the list of traditional methods we can use to iterate over arrays in JS:

  1. for loop
  2. optimized for loop
  3. for-of loop
  4. for-in loop - possible, but undesireable, because of quirks - basically, the issue is that prototype member variables are iterated over in the for in loop along with our array members
  5. while loop
  6. do while loop

Of these 6 looping methods above, the ones that are most commonly used are probably for and for-of.

There are also a number of functional methods for looping over arrays in JS. These methods exist on the Array.prototype, and include:

  1. Array.prototype.forEach
  2. Array.prototype.filter
  3. Array.prototype.filter followed by Array.prototype.each so as to avoid the problem of not being able to break or continue
  4. Array.prototype.map
  5. Array.prototype.reduce
  6. Array.prototype.some
  7. Array.prototype.every
  8. Array.prototype.includes
  9. Array.prototype.find
  10. Array.prototype.sort

Now that we have a list of all the different ways of looping over arrays, let’s see an example in which we’ll loop over the exact same array, using all of these methods.

The array we’ll be looping over loops like this:

let people = [
    { name: "John", age: 30, heightCm: 190, kilos: 110, salary: 5000, gender: "male" },
    { name: "Jane", age: 20, heightCm: 170, kilos: 65, salary: 8000, gender: "female" },
    { name: "Jack", age: 55, heightCm: 180, kilos: 75, salary: 4000, gender: "male" },
    { name: "Jill", age: 80, heightCm: 160, kilos: 50, salary: "", gender: "female" },
    { name: "James", age: 15, heightCm: 189, kilos: 77, salary: "", gender: "male" },
    { name: "Joanna", age: 15, heightCm: 168, kilos: 58, salary: "", gender: "female" },
    { name: "Bob", age: 50, heightCm: 170, kilos: 60, salary: 5000, gender: "male" },
]

Now that we have the array, let’s loop over it.

1. Using the for loop

for(let i = 0; i < people.length; i++) {
    console.log(`${people[i].name} is ${people[i].age} and weighs ${people[i].kilos} kilograms.`)
}

The for loop is pretty straightforward, we loop over each member of the array and print out a message to the console based on the current “row” of data.

But, what about ordering our characters by age, for example? Here it is:

for(let i = 0; i < arr.length; i++) {
    // ??? what to put here ???
}

It seems kind of difficult to wrap our heads around how to go on about this if we haven’t seen it done before. The trick is in using a nested for loop.

for(let i = 0; i < people.length; i++) {
    for(let j = 0; j < people.length; j++) {
        if(people[i].age > people[j].age) {
            let originalValue = people[i]; // store the original position in array so we can swap it
            people[i] = people[j]; // move up the original position in array
            people[j] = originalValue; // set to original Value (complete the swap)
        }
    }
}

It would be interesting to also turn on the debugger so as to inspect what happens in the inner for loop on each iteration:

for(let i = 0; i < people.length; i++) {
    for(let j = 0; j < people.length; j++) {
        if(people[i].age > people[j].age) {
            let originalValue = people[i]; // store the original position in array so we can swap it
            people[i] = people[j]; // move up the original position in array
            people[j] = originalValue; // set to original Value (complete the swap)
        }
    }
}

Another quick tip: our loop is now ordering the array from oldest to youngest. If we wanted to order it from youngest to oldest, we’d change just one line:

if(people[i].age < people[j].age) {

We’ve simply changed the original greater than operator (i.e >), to the less than operator (i.e <).

2. Using the “optimized” for loop

The trick with the “optimized” for loop is simply the fact that we’re “caching” the array length, thus making the execution of the for loop a bit faster:

for(let i = 0, arrLength = people.length; i < arrLength; i++){
    // etc.
}

Everything else is the same as in the original for loop example.

3. Looping over a JS array with for-of

ES6 introduced iterables to the JavaScript language. Along came a new flavor of the for loop, the for-of.

Any iterable object and any generator can be looped over using for-of as follows:

for (const person of people) {
    console.log(`${person.name} is ${person.age} and weighs ${person.kilos} kilograms.`)
}

4. Don’t loop over a JS array with for-in

It is possible to loop over a JS array with for-in. However, this should never be done.

There are two problems with looping over a JS array with for-in:

  1. It enumerates through all the properties; including those associated to the Object (even properties added onto the Object by the user)
  2. The order of elements is not neccessarily followed

While the second problem is not a major turn-off, the first problem is really a deal-breaker. Here’s why:

Object.prototype.myAddition = "whatever";

for (const person in people) {
    console.log( people[person] )
}

The output? It included “whatever”:

{ name: "John", age: 30 ...}
{ name: "Jane", age: 20 ...}
{ name: "Jack", age: 55 ...}
{ name: "Jill", age: 80 ...}
{ name: "James", age: 15 ...}
{ name: "Joanna", age: 15 ...}
{ name: "Bob", age: 50 ...}
whatever

The people temporary variable of our for-in loop is actually same as the usual i “iterator variable” in a regular for loop. Here’s the proof:

Object.prototype.myAddition = "whatever";

for (const person in people) {
    console.log( person )
}

What do you think the above code will output? It will actually output numbers from 0 to 6, for all the members of the people array. Additionally, it will also print out myAddition, the name of the property we added to Object.prototype.

5. Looping over a JS array with the while loop

The while loop is very similar to a for loop. Here’s how it works with our example.

let count = 0;
while(person = people[count++]) {
    console.log(`${person.name} is ${person.age} and weighs ${person.kilos} kilograms.`)
}

// alternative approach:
let count = 0;
while (people.length > count) {
    console.log(`${people[count].name} is ${people[count].age} and weighs ${people[count].kilos} kilograms.`);
    count++;
}

6. Looping over a JS array with the do while loop

The do while loop is almost identical to the while loop. The difference here is that it will always run at least once, contrary to the while loop for which it is possible not to be run at all under some conditions.

let count = 0;
do {
    console.log(`${person.name} is ${person.age} and weighs ${person.kilos} kilograms.`);
    count++;
}
while(person = people[count++]);

// alternative approach
let count = 0;
do {
    console.log(`${people[count].name} is ${people[count].age} and weighs ${people[count].kilos} kilograms.`);
    count++;
}
while(people.length > count);

It’s common to use i or key instead of count. Whatever works for you, that’s what you should use.

Functional approach to looping over arrays in JS

The functional approach to looping over arrays in JS involves different methods on the Array.prototype: forEach, each, filter, map, reduce, some, sort, and find. We’ll discuss examples of each one of them in use, next.

7. Looping over arrays in JS with forEach

The forEach method runs over each member of the array and runs a function we pass as an argument of the forEach.

Simple example:

['one', 'two', 'three'].forEach( function(memberInArray) {
    console.log(memberInArray);
});

The above code outputs:

one
two
three

Very often, the forEach method’s argument is passed in as an ES6 function. Here’s the above example again, only this time with the arrow function instead of an ES5 function above:

['one', 'two', 'three'].forEach( memberInArray => console.log(memberInArray) );

The resulting output is the same.

Now we can try the forEach on our people array:

people.forEach( person => {
    console.log(`${person.name} is ${person.age} and weighs ${person.kilos} kilograms.`)
})

The forEach actually takes more than just one argument in the callback function (i.e the anonymous function that’s passed to it as an argument). Here’s the list of arguments that the forEach callback can accept:

  1. current member of array that’s being iterated over ( person in the above example )
  2. the index of the currently looped over member of array (usually an i or an index)
  3. the array itself - i.e. the array that the forEach is used on ( people in the above example )
  4. the thisArg - the value of this when executing the callback ( we’re not gonna discuss it here )

Ok, so out of the 4 possible arguments passed to the forEach callback function, we’re going to discuss how to use 3.

So why would we need an index (the second variable)? Here’s one possible reason:

people.forEach( (person, index) => {
    console.log(`${index}. ${person.name} is ${person.age} and weighs ${person.kilos} kilograms.`);
})

Doing this would log out the following in the console:

0. John is 30 and weighs 110 kilograms
1. Jane is 20 and weighs 65 kilograms.
2. Jack is 55 and weighs 75 kilograms.
3. Jill is 80 and weighs 50 kilograms.
4. James is 15 and weighs 77 kilograms.
5. Joanna is 15 and weighs 58 kilograms.
6. Bob is 50 and weighs 60 kilograms.

So this is an easy way to add a count on the output.

But why in the world would we need to give to the array that we’re looping over with forEach, the array itself?

Initially, it might seem strange, but actually there are completely valid scenarios for this. For example, if we use a named function as the callback of our forEach:

let namedFn = function(item, index, arr) {
    console.log(`${index}. ${item.name} is ${item.age} and weighs ${item.kilos} kilograms.`);
}

Now we can pass the named function as a callback to our forEach:

people.forEach( namedFn );

A nice thing about this approach is that you can now use this namedFn as the callback on any array. For example:

let people2 = [
    { name: "Michael Jordan", age: 55, kilos: 90  },
    { name: "Luka Doncic", age: 20, kilos: 85 }
]

people2.forEach( namedFn );

Now we’d get back:

0. Michael Jordan is 55 and weighs 90 kilograms.
1. Luka Doncic is 20 and weighs 85 kilograms.

And if we ran it on our initial people array, we’d get back the output for the different array, using almost the same syntax.

8. Looping over arrays in JS with Array.prototype.filter

The filter runs a test on a given array:

people.filter( eachPerson => eachPerson.age > 50 );

In the above example, we’re running the filter method on eachPerson in the people array. The test we’re running on eachPerson is whether their age is over 50.

This is the result running the filter on our people array:

{name: "Jack", age: 55, heightCm: 180 ...}
{name: "Jill", age: 80, heightCm: 160 ...}

Now comes the fun part, combining the filter and forEach method to get the same result as using break to stop iterating over the regular for loop.

9. Using Array.prototype.filter followed by Array.prototype.forEach

To understand this approach, we first need to look at when and how we need to use break in a plain for loop in JavaScript.

(function myFunction() {
  var text = ""
  var i;
  for (i = Math.floor(Math.random() *100); i < 100; i++) {
    if (i < 75) {
      break;
    }
    text += "The number is " + i + "<br>";
  }
  document.body.innerHTML = "";
  document.body.innerHTML = text;
})()

The above function is just a simple IIFE (immediately-invoked function expression) - a function that gets defined and called in one fell swoop.

The function sets the value of the i variable in the for loop to a random integer, whose value is any number between 0 and 100.

The if condition checks if the random value of i is less then 75, and if it is, we simply break out of the loop. This means that the line following the if statement will only be run if the random value of i is set to any number between 75 and 100.

This simple example shows when we’d use break. There’s another keyword: continue. The continue keyword can be thought of as a “soft break”. It doesn’t actually break out of the loop, but rather skips the current iteration of the loop and moves on to the next one:

(function myFunction() {
  var text = ""
  var i;
  for (i = Math.floor(Math.random() *100); i < 100; i++) {
    if (i < 75) {
      continue;
    }
    text += "The number is " + i + "<br>";
  }
  document.body.innerHTML = "";
  document.body.innerHTML = text;
})()

What the above code does is: for any number under 75, the current iteration will be skipped; in other words, if the random value of i is any number under 75, all the numbers between 75 and 100 will always be printed. This is in contrast to the break keyword, which would completely stop the for loop, i.e break out of it entirely.

Now that we understand the dynamics of break and continue, let’s run a regular, iterative for loop on our people array:

console.log("Here's the list of skinny people:")
for(let i = 0; i < people.length; i++) {
    if ( people[i].kilos > 70 ) {
        continue;
    }
    console.log(`
        ${people[i].name} is ${people[i].age} and weighs ${people[i].kilos} kgs.
    `)
}

The output is as follows:

Jane is 20 and weighs 65 kilograms.
Jill is 80 and weighs 50 kilograms.
Joanna is 15 and weighs 58 kilograms.
Bob is 50 and weighs 60 kilograms.

If we used the break keyword on the exact same code above, we’d get no results back. Why? Because we’d break out of the for loop entirely, as soon as we’d run the if statement on the first person, John. Since we’re running break for any person that’s over 70 kilos of weight, as soon as we hit that condition, we break out of the loop.

This leads us to the conclusion that in cases when we have an array like our people array, it makes more sense to use the continue keyword in an if statement inside a for loop.

Now that we’ve understood just what the break and continue keywords do in for loops, we need to be able to know how to get the same results using the functional approach. It’s a two step process.

First, we filter the array. This serves the same purpose that the continue keyword does, skipping over array members that meet certain criteria.

Next, we run the “functional for loop” - the forEach, on remaining array members, i.e on array members that pass the filter.

With filter, we produce a whole new array, leaving the original array intact.

So:

people.filter(person => person.age > 50)
      .forEach(person => `${person.name} is over 50 years of age.` )

Of course, we also need to bind a variable name to the new array this produces:

let over50 = people.filter(person => person.age > 50)
                   .forEach(person => console.log(`
                            ${person.name} is over 50 years of age.
                        `) 
                    )

10. Using Array.prototype.map

Similar to filter, the map method produces a new array from the existing array.

A trivial example of the map would be running some kind of mathematical operation on an array of numbers. For our example, let’s say that we need to format all the objects in the people array a bit differently. Would we ever need to do that in practice? Of course! Maybe we get back some weird JSON data from an API, and we need to arrange the objects so it can be consumed in our frontend.

Here’s how we could reformat array objects using the map method:

let reformattedPeople = people.map(obj => {
    let returnedObj = {};
    returnedObj[obj.name] = obj.age;
    return returnedObj;
})

The above code will use the existing 7 objects in the people array, to produce the following 7 objects in the reformattedPeople array:

[
    {John: 30},
    {Jane: 20},
    {Jack: 55},
    {Jill: 80},
    {James: 15},
    {Joanna: 15},
    {Bob: 50}
]

11. Using Array.prototype.reduce

The reduce method is one of those that needs to be practiced a few times before we really understand it. Once we do, however, it opens up lots of possibilities.

The first thing to know about reduce is that it’s just another iterator method. An iterator is any array method that runs a used-provided function on each array member.

One way to explain reduce is to compare it with map.

Consider running the map array iterator method on this array:

[1,2,3,4,5].map( item => item*2 );

The above code will return:

[2,4,6,8,10]

While the map iterator returns an array, the reduce iterator returns an accumulator.

Here’s another way of looking at reduce: It’s just an iterator method which takes an operator and puts the operator between each member of the array. For example, running reduce on [1,2,3]:

[1,2,3].reduce ( (accumulator, currentValue) => accumulator + currentValue );
// returns: 6

We can look at it like this too:

  1. We have an array of three numbers. Initially, the accumulator’s value is 0, because we haven’t given it an initial value (which is possible, and completely legitimate, as we’ll see later). Thus, on the first iteration, this is what the callback function’s values will be: ( 0, 1) => 0 + 1.
  2. On the second iteration, the value will be the total amount of the previous iterations, as the value of the accumulator, and the currentValue will be 2, so: ( 1, 2 ) => 1 + 2.
  3. On the third iteration, the value will be the total amount of all the previous iterations for the accumulator, plus the currentValue for this iteration: ( 3, 3 ) => 3 + 3.

This ends all the iterations, and the return value is obviously 6.

The reduce iterator, of course, takes more than 2 arguments in the callback function. The additional arguments that it takes are the current iteration’s index in the array and the array itself.

Here’s the full “definition” for the reduce iterator method:

Array.prototype.reduce( 
    (accumulator, currentValue, currentIndex, arrayItself ) => {
        // whatever calculation you want to perfom on the array
    }
)

There’s only one thing missing from the code above, and that’s the reduce method’s callback function accumulator’s initial value. Here’s the reduce method’s “signature” with accumulator’s initial value specified:

Array.prototype.reduce( callbackFn, initialAccValue);

Obviously, in the code above, the callbackFn is actually this piece of code:

(accumulator, currentValue, currentIndex, arrayItself) => {
    // whatever calc...
}

When we put all of this together, our reduce iterator’s definition might also look like this:

Array.prototype.reduce( 
    (accumulator, currentValue, currentIndex, arrayItself ) => {
        // whatever calculation you want to perfom on the array
    }, initialAccValue);
)

Here are some use cases for the reduce array iterator method:

  1. To sum up an array of amounts
  2. To sum up values from specific object keys in an array of objects
  3. To sum up values from an array of objects, excluding certain keys based on some criteria
  4. To find an average value of an array
  5. To count the number of times an item repeats in an array
  6. To flatten an array of arrays
  7. To build a pipeline of functions to execute (getting a really functional vibe here)
  8. To rearrange an array of objects into a different array of objects so that they are grouped by a specific property
  9. To extract and combine all the values from array values stores as keys in an array of objects
  10. To remove duplicate items in an array (an alternative approach to doing this using the Set data structure)
  11. To run promises in a sequence
  12. To re-write an implementation of the map array iterator method

As we can see, the reduce method is very flexible and it is worth the investement of time to learn how to use it.

Without going into more complex scenarios listed above, let’s instead see a simple example of summing up an array of amounts.

Let’s say we want to calculate a shopping cart for drinks bought at a concert:

[ 9.99, 10.99, 11.99, 12.99 ].reduce( (acc, currentValue) => acc + currentValue)`

This example returns 45.96. We can even use the accumulator’s initial value to count in, for example, the fixed price of a ticket. Let’s say the ticket’s price was 50. Thus:

[ 9.99, 10.99, 11.99, 12.99 ].reduce( (acc, currentValue) => { return acc + currentValue }, 50)`

Easy stuff! Obviously, the returned value we’d receive from this operation would be 95.96 - the total cost of the concert ticket and drinks bought.

12. Using Array.prototype.some

The some iterator method checks for at least one array element that passes a test, returning a Boolean true or false.

In other words, the some method labels the following statement either true or false: There is at least one member of the array that passes the test.

For example:

// testing if value is greater than 100
let peopleTest = function(person, index, array) {
    return person.kilos > 100
}

people.some( peopleTest )

The above code, when run, will return true, because John has 110 kilos of weight.

13. Array.prototype.every

While the some method checks for presence of at least one array item that passes the test, the every method checks if all items pass the test.

For example:

// testing if value is greater than 10
let peopleTest = function(person, index, array) {
    return person.kilos > 10
}

people.every( peopleTest )

We’re checking if all the people weigh over 10 kilograms. Since the values in the people array are realistic, the answer we get is obviously true.

Let’s test another one:

// testing if value is less than 109
let peopleTest = function(person, index, array) {
    return person.kilos < 110
}

people.every( peopleTest )

This time, we get back false, because John in our people array weighs exactly 110 kilograms.

14. Using Array.prototype.find

The find method is a weird iterator. It will iterate all the members in the entire array, only if they all don’t pass the test.

You can imagine a valuable is gone missing and we’re trying to find the thief. The first person that has the valuable in their pocket is the thief, so there’s no point in iterating further.

Here’s an example:

// testing if value is less than 109
let peopleTest = function(person, index, array) {
    return person.kilos < 110
}

people.find( peopleTest )

The returned value is:

{name: "Jane", age: 20, heightCm: 170, kilos: 65, salary: 8000, …}

Since John weighs 110 kilograms, the find method returned the very first person after him as the match, because she weighs only 65 kilograms, which is well under the 110 kilograms which was the passing test condition.

15. Using Array.prototype.sort

While the sort method is also an array iterator, we’ve already covered it earlier in this article, under the title “Sorting arrays with Array.sort”.

Looping over arrays: Conclusion

With so many options described above, one of the things to look at before you loop over an array is: why are you looping?

Once you have an idea of what exactly it is that you’re trying to achieve, you can use one of many built-in array methods or looping constructs to do the task at hand.

Feel free to check out my work here: