Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

JavaScript Array Methods

Chapter 28 29 mins

Learning outcomes:

  1. Joining arrays together using concat()
  2. Filling an array using fill()
  3. Using slice() to slice an array
  4. Adding/removing elements at the end — push() and pop()
  5. Adding/removing elements at the start — unshift() and shift()
  6. Adding/removing elements at an arbitrary index — splice()
  7. Reversing an array using reverse()
  8. Finding the index of an element using indexOf() and lastIndexOf()
  9. Existential and universal quantification using some() and every()
  10. Filtering items via filter()
  11. Joining array elements using join()
  12. Mapping to a new array via map()

Introduction

Arrays are highly useful for storing ordered collections of data, but not until they are blended together with array properties and methods.

In this chapter we shall get an overview of the most fascinating methods available to all array instances and the all-time favourite length property.

Joining multiple arrays together

To join — or better to say, concatenate — two or more arrays together into a single array we could use the concat() method.

Call it on a given array whose elements you want to appear first in the final array and then pass the rest of arrays one-by-one as arguments.

Something as follows:

arr1.concat(arr2, arr3, ...., arrN)

The order in which the arrays appear in the expression above is exactly the same order in which there elements are laid out in the final away.

The concat() method does not modify the original array (or any other array). It returns a new array composed by joining all the given arrays together.

The method concat() can be useful often times. Let's say we have three different lists of numbers which represent the marks of three different students in recent exams out of 100:

var a = [75, 54, 70],
var b = [94, 60, 78];
var c = [67, 80, 81];

Now we would like to display all these numbers in sorted.

For this we'll need to first join all the three lists together and then perform the sorting on the array obtained in the end. In the code below, we accomplish this idea and finally log the resulting array:

var a = [75, 54, 70];
var b = [94, 60, 78];
var c = [67, 80, 81];

var allNums = a.concat(b, c);
console.log(allNums.sort(function(a, b) { return a - b; }));
[54, 60, 67, 70, 75, 78, 80, 81, 94]

Filling an array

If we wish to set each element of an array to the same value, we could iterate over it and assign each index that very value. An example follows:

To fill an array with a single value in a single command, we could use the fill() method.

Just pass it the respective value and the given array would be filled with that value at each index.

arr.fill(value[, start[, end]])

By default, start and end default to 0 and arr.length, respectively. That is, every element would be replaced by value. Explicitly providing a value to these parameters would fill the array only upto the specified length.

The return value of fill() is the filled array. Note that fill() mutates the original array.

Consider the snippet below:

[1, 2, 3, 4].fill(0)
[0, 0, 0, 0]
[1, true, 'Hello'].fill(100)
[100, 100, 100]

If the array is empty, there won't be any consequene of calling fill() on it, as can be seen below:

[].fill(0)
[]
[].fill(0, 0, 3)
[]

In the last statement here, you might expect the method to fill the first three indexes of the array with 0 but this does not happen. The reason is because the array is empty, i.e. it's length is equal to 0.

The fill() method doesn't process empty arrays.

One trick we could use with fill() is to initialize an array to a given length using Array(n) and then fill it with a given value. This could be extremely handy when we have to work with a preinitialized array, where otherwise creating the array manually using literals would be quite a strenous activity.

Let's quickly consider an example. Suppose we have to create an array holding 100 values each initialized to 0. As you would agree, doing so manually would be quite repetitive and monotonous.

A better way is to create an array to the desired length using Array(100) and then fill it with the value 0.

Shown below is an illustration:

var arr = Array(100).fill(0);

console.log(arr[0]);
console.log(arr[50]);
console.log(arr[99]);
0
0
0

Voila! All of the three elements inspected are equal to 0.

Slicing an array

To extract out a given subarray from an array, we could use the slice() method.

The slice() method takes a starting (inclusive) and ending index (exclusive) and returns a copy of the array in that range.

Shown below is its syntax:

arr.slice([start [, end]])

start specifies the index where to start the slicing. This is inclusive, and defaults to 0. end specifies the index where to end the slicing. This is exclusive, and defaults to arr.length.

We saw a similar slice() method, with exactly the same syntax of arguments, for strings back in the JavaScript String Methods chapter.

Let's consider a couple of examples:

var nums = [1, 2, 3, 4, 5];

console.log(nums.slice(0, 0)); // []
console.log(nums.slice(0, 1)); // [1]
console.log(nums.slice(1, 4)); // [2, 3, 4]

In the first statement, calling slice(0, 0) returns an empty array because the slicing begins at 0 and ends before 0 (at -1, which is clearly impossible!).

In the second statement, calling slice(0, 1) returns the array [1] by beginning slicing at index 0 and ending it just before 1 (i.e 0).

In the last statement, calling slice(1, 4) returns the array [2, 3, 4] because slicing this time begins at index 1 and ends just before index 4. This accounts for the indexes 1, 2 and 3 (4 being exclusive).

Figure out the return value of nums.slice() for the nums array above.

Keep in mind the default values of both the start and end arguments.

  • undefined
  • []
  • [1, 2, 3, 4]

Adding/removing elements at the end

As we saw in the previous chapter, to add an element, or a set of elements, at the end of an array, we could use the push() method.

The push() method adds an element to the end of an array.

The syntax is pretty straightforward:

arr.push(item1, item2, ..., itemN)

We could pass just one element item1 to be added to arr; or pass a set of items item1, item2, all the way to itemN, to be added to the array.

Note that push() changes the length of the calling array.

Let's use push() to add a couple of elements to an array:

var nums = [1, 2];

nums.push(3);
console.log(nums);

nums.push(4);
console.log(nums);
[1, 2, 3]
[1, 2, 3, 4]

In a similar way that we could add an element to the end of an array, we could remove it from there as well. For this, we have the pop() method.

The pop() method removes an element from the end of an array.

Since pop() merely removes the last element from an array, it doesn't require any arguments:

arr.pop()

pop() returns the element removed. This is useful because, often times, we have to use the value in the program before losing it completely.

Following from the last code, let's remove the last two elements using pop():

var nums = [1, 2];

nums.push(3);
nums.push(4);
console.log(nums);

console.log('Removing', nums.pop());
console.log('Removing', nums.pop());
console.log(nums);
[1, 2, 3, 4]
Removing 4
Removing 3
[1, 2]

Simple, wasn't it?

Adding/removing elements at the start

As we saw just right now, push() and pop() serve to add and remove stuff from the end of a given array. In JavaScript, and most programming languages that support dynamic arrays, we could do so at the start of the array as well.

The methods used in this case are unshift() and shift().

The unshift() method adds an element to the start of an array.

Parameter-wise, it's same as push():

arr.unshift(item1, item2, ..., itemN)

The given arguments are added to the start of arr. Simple.

Let's consider a quick example:

var nums = [1, 2];

nums.unshift(3);
console.log(nums);

nums.unshift(4);
console.log(nums);
[3, 1, 2]
[4, 3, 1, 2]

To remove an element from the start of an array, we use the shift() method.

The shift() method removes an element from the start of an array.

It's syntactically the same as pop():

arr.shift()

The return value of shift() is the element removed.

Let's consider a quick example following from the last code snippet above:

var nums = [1, 2];

nums.unshift(3);
nums.unshift(4);
console.log(nums);

console.log('Removing', nums.shift());
console.log('Removing', nums.shift());
console.log(nums);
[4, 3, 1, 2]
Removing 4
Removing 3
[1, 2]

Adding/removing elements at arbitrary indices

To add and/or remove stuff from an array starting at an arbitrary index, instead of the beginning or end of the array, we have the splice() method at our dispense.

splice() is meant to add/remove elements from an array, in-place, starting from a given index.

Note that splice() mutates the original array.

Here's its syntax:

arr.splice([index[, deleteCount[, item1[, item2[, ...[, itemN]]]]]])
  1. index is the index where to begin the addition and/or removal of stuff. It defaults to 0.
  2. deleteCount specifies the number of items to delete starting from the position index. If index is not specified, i.e. splice() is called without any arguments, deleteCount is 0. Otherwise, it is set to arr.length - index i.e. removes all elements upto the end of the array, starting from index.
  3. item1, item2, all the way itemN, specify the elements to add at index. If omitted, nothing is added.

The return value of splice() is an array holding the deleted items of the main array. If nothing is deleted, i.e. deleteCount is 0, an empty array is returned.

Time for some examples...

Let's say we have the following array and want to remove the second element from it:

var arr = [1, 50, -6, -20, 22];

How would we do so?

Well, the second element is at index 1, and this is the position where the removal should begin; hence the first index arg to splice() becomes 1.

Moving on, since only one element is to be deleted, deleteCount would also be 1. And finally, because nothing ought to be added, no args follow along.

Below, we perform the removal, and log both arr and the array holding the removed item:

var arr = [1, 50, -6, -20, 22];
var deletedArr = arr.splice(1, 1);

console.log(arr);
console.log(deletedArr);
[1, -6, -20, 22]
[50]

See how the deleted element 50 is accessible as an element of deletedArr.

In a real-world application, you might want to work with the set of removed items and that's where the return value of splice() could help.

Let's see a couple more examples.

Say we have to delete the second last element from an array arr. What would the set of args to splice() be?

Simple — arr.splice(-2, 1).

An illustration follows:

var arr = [1, 50, -6, -20, 22];
var deletedArr = arr.splice(-2, 1);

console.log(arr);
console.log(deletedArr);
[1, 50, -6, 22]
[-20]

What if we want to remove nothing from an array, but rather add two elements at the second position? Hmm..

We'll call arr.splice(1, 0, ele1, ele2).

An illustration follows:

var arr = [1, 50, -6, -20, 22];
var deletedArr = arr.splice(1, 0, 'Hello', 'World!');

console.log(arr);
console.log(deletedArr);
[1, "Hello", "World!", 50, -6, -20, 22]
[]

Since nothing is removed in the array arr above, splice() returns an empty array.

Calling splice() without any arguments merely returns an empty array:

var arr = [1, 2, 3];

console.log(arr.splice());

Reversing an array

Want to switch the order of elements of an array? Simply use the reverse() method.

The reverse() method reverses the order of elements of a given array, in place.

It's simple in nature:

arr.reverse()

Note that as with sort(), reverse() mutates the original array and returns it back.

Shown below is an example:

var subs = ["Chemistry", "Physics", "Math"];

console.log(subs.reverse());
console.log(subs);
["Math", "Physics", "Chemistry"]
["Math", "Physics", "Chemistry"]

In the first log statement, the reverse() method returns back the reversed version of subs and this is logged in the console. The second log statement outputs the same array as before. This confirms that the original array subs was mutated by subs.reverse().

If you don't want to mess up with the order of elements in the original array, then make its copy and call the reverse() method on that copy.

Finding index of an element

Do you recall the indexOf() and lastIndexOf() methods all the way back from the JavaScript String Methods chapter?

Both these methods are available on array instances as well and serve a similar purpose — to return the index of a given element.

Let's see each one...

The indexOf() method finds a given element in an array and returns its index; or otherwise the value -1.

The method is comprised of two parameters:

arr.indexOf(value[, index])

value is the value to look for in arr while index is the index where to start the searching. This defaults to 0 i.e the beginning of the array.

The indexOf() method finds a match for value in arr using a strict-equality comparison (the one employed by the === operator).

Shown below are a couple of examples:

[1, 2, 3, 4].indexOf(1)
0
[1, 2, 3, 4].indexOf(4)
3
[1, 2, 3, 4].indexOf(5)
-1
[1, 2, 3, 4].indexOf("1")
-1
[1, true, true, false].indexOf(true)
1
Calling indexOf() without an argument would make value equal to undefined.

Similar to indexOf(), which finds the first match for a given value, the lastIndexOf() method finds the index of the last match of a given value.

The lastIndexOf() method finds a given element in an array, starting from the end, and returns its index; or otherwise the value -1.

Syntactically, it's identical to indexOf():

arr.lastIndexOf(value[, index])

Consider the snippet below:

[1, 2, 3, 4].lastIndexOf(1)
0
[1, 2, 3, 4].lastIndexOf(4)
3
[1, 2, 3, 4].lastIndexOf(5)
-1
[1, 2, 3, 4].lastIndexOf("1")
-1
[1, true, true, false].lastIndexOf(true)
2
[1, 1, 0, 1].lastIndexOf(1)
3

Existential and universal quantification

In elementary logic, specifically in predicate logic, there is this idea of some item in a given set of items meeting a certain condition. We call this existential quantification.

A similar idea is that of universal quantification, where every single element meets the given condition.

These ideas of checking whether in a set of items, at least one or all elements meet a certain condition are present in JavaScript arrays as well. They are exposed by the some() and every() methods, respectively.

The method some() takes a function and returns true if the function evaluates to true for at least one element in the calling array.

Time to see its syntax:

arr.some(callbackFn)

callbackFn is a function that is run for every element of arr until it evaluates down to true. Here's the syntax of the callback function:

callbackFn(element, index, array, thisValue)

  1. element is the element of arr currently under inspection.
  2. index is the index of element.
  3. array holds a reference to arr.
  4. thisValue is the value to be used in place of this inside the callback function.

Let's consider a quick example.

Say we want to confirm whether in a list of numbers, there is at least on square number. We could solve this by laying out the callback function as follows:

function isSquare(element) {
   return Number.isInteger(element ** 0.5);
}

If any one element in the list of numbers is a square isSquare() would return true for it and hence cause some() to return true as well.

Shown below are a couple of examples:

function isSquare(element) {
   return Number.isInteger(element ** 0.5);
}

var nums = [1, 2, 3];
console.log(`Square in ${nums}`, nums.some(isSquare));

nums = [2, 3, 4];
console.log(`Square in ${nums}`, nums.some(isSquare));

nums = [2, 3, 5, 7];
console.log(`Square in ${nums}`, nums.some(isSquare));

nums = [2, 3, 5, 7, 49, 100];
console.log(`Square in ${nums}`, nums.some(isSquare));
Square in [1, 2, 3]: true
Square in [2, 3, 4]: true
Square in [2, 3, 5, 7]: false
Square in [2, 3, 5, 7, 49, 100]: true

Following from the fact that for some() to return true, there has to be at least one element in the array for which the callback function returns true, when the array is empty i.e. has not elements, some() returns false.

Consider the following code:

function isSquare(element) {
   return Number.isInteger(element ** 0.5);
}

console.log([].some(isSquare));
false

In the same way, to check whether every single element in an array meets a given condition, we could use the every() method.

The method every() takes a function and returns true if the function evaluates to true for every single element in the calling array, or otherwise false.

It's syntactically identical to some():

arr.every(callbackFn)

Check out the syntax for callbackFn above.

The main difference is that the given callback function is run for every element in the given array and if, for any one, it returns false, every() returns false as well. It's only when the function returns true for every element in the array that every() returns true.

Let's say we want to confirm whether a student passed in all exams. The passing marks are above 50. If the student's marks were modeled by an array marks, we could use every() to solve this task.

Shown below is an illustration:

function above50(marks) {
   return marks >= 50;
}

var marksList = [35, 80, 54, 90, 60];
console.log(marksList.every(above50));

marksList = [78, 86, 70, 95, 71];
console.log(marksList.every(above50));
false
true

Following from the fact that for every() to return false, there has to be at least one element in the array for which the callback function returns false, when the array is empty i.e. has not elements, every() returns true.

Consider the following code:

function above50(marks) {
   return marks >= 50;
}

console.log([].every(above50));
true

Filtering elements

To obtain only those elements from an array that meet a given condition, we use the filter() method.

filter() takes in a callback function and returns an array containing all the elements in the calling array for which the callback function returns true.

If you think on for a second, the word 'filter' is quite a sensible name for this method. It says to filter out elements from an array based on a given condition.

Pretty clever naming!

Say we want to extract out all positive values from an array of numbers. For this we'll set up the callback function as follows:

function positiveNumber(num) {
   return num > 0;
}

This would return true only for those numbers that are greater than 0. Let's use this function along with filter() on a couple of arrays and see the outcome in each case:

function positiveNumber(num) {
   return num > 0;
}

var nums = [10, 5, -4, -1, 50, 34, -27];
console.log(nums.filter(positiveNumber));

nums = [0, 15, 0, -6, -1, -4, -0.5, 3.1, 10.5];
console.log(nums.filter(positiveNumber));
[10, 5, 50, 34]
[15, 3.1, 10.5]
This feature of filtering out elements from an array could also be accomplished using loops, but at the cost of longer and more complicated code. The filter() method is no doubt worth it!

Create an array evens by filtering out all the even-indexed elements from the following nums array:

var nums = [1, 10, 5, 33, 198, 0, 5, 8];

Your evens array shall be equal to [1, 5, 198, 5] as these elements have even indexes in nums0, 2, 4, and 6 respectively.

Think of the second parameter of the callback function passed to filter().

var nums = [1, 10, 5, 33, 198, 0, 5, 8];

var evens = nums.filter(function(e, i) {
   return i % 2 === 0;
});

Joining elements together

When working with arrays, it's extremely common to go into a string representation by joining the individual elements together.

If we just want to join the elements with a comma in betweeen we can call the toString() method,or simply use the array in a string concatenation context.

Both of these are shown below:

[1, 2, 3, 4].toString()
1,2,3,4
[1, 2, 3, 4] + ''
1,2,3,4
'The numbers are: ' + [1, 2, 3, 4]
The numbers are: 1,2,3,4

However, if we want some other separator, we could use the join() method.

It accepts a single string argument which is the separator to put in between the elements:

arr.join([separator])

By default, separator is set to ',', which means that arr.join() is effectively the same as calling arr.toString().

The return value of the join() method is a string containing all elements of arr separated by separator.

A separator is sometimes also known as a delimiter.

A common separator used out there is a single space — ' '.

In the code below, we create an array nums and then output it with each element being separated from the other one using a space:

var nums = [1, 2, 10, 50, 100];

console.log(nums.join(' '));
1 2 10 50 100

Mapping an array

It's a common idea to iterate over an array and map each of its elements onto a new element. These mapped elements are put in a new array.

For instance, suppose we have a list of positive integers. We could create a list of squares outt= of it by mapping each integer to the square of that integer. Similarly, we could even obtain a list of cubes using this same list of positive integers.

In JavaScript, we could use the map() method to create a new array based on a given array with a mapping function.

The map() method takes a function and returns a new array comprised of elements returned by the function for each element of the calling array.

Let's see its syntax:

arr.map(mappingFn[, thisValue])

Given an element (and other arguments), the mapping function mappingFn simply returns the new value which ought to be put in the new array. Its syntax is similar to that of the callback function passed to some(), every(), filter() etc.

mappingFn(element, index, thisValue)

  1. element is the element of arr currently under inspection.
  2. index is the index of element.
  3. array holds a reference to arr.

The thisValue argument specifies the value that this refers to inside the callback function. Almost always, you won't find yourself in need of this.

Let's consider a couple of examples...

Below we have an array ints which is used to create two more arrays squares and cubes:

function toSquare(int) { return int ** 2 };
function toCube(int) { return int ** 3 };

var ints = [0, 1, 2, 3, 4, 5];

var squares = ints.map(toSquare);
console.log(squares);

var cubes = ints.map(toCube);
console.log(cubes);

// let's see if ints has been modified
console.log(ints);
[0, 1, 4, 9, 16, 25]
[0, 1, 8, 27, 64, 125]
[0, 1, 2, 3, 4, 5]

The last log here confirms the fact that calling map() on an array does not mutate it.

Going ahead, a common practice you'll see in coding competitions out there is to use this notion of mapping to convert a list of stringified numbers into a list of numbers.

In the code below, we convert a string of space-delimited numbers into an array of numbers using a couple of handy methods, including map():

var str = '10 -5 40 1 0 0 3';

var nums = str.split(' ').map(Number);
console.log(nums);
[10, -5, 40, 1, 0, 0, 3]

Time to understand what's happening over here...

str.split(' ') breaks apart str at each space (' ') character and returns back an array of the left-over strings, as follows:

str.split(' ')
["10", "-5", "40", "1", "0", "0", "3"]

Next up, map() goes over this array of strings and runs the Number() function over each string. Recall that, given an argument, Number() converts it into a number.

Hence, for each string in the array of string shown above, the return value of Number() is the equivalent number which is put in the array returned by map().

A very elegant way to convert a string of numbers into an array of numbers!