ES6 New Array Methods

Introduction

After ES6 was released, I have seen that many developers are still unaware of the recently added functions of the Array object. Thereby, I decided to create this article to spread the information and hoping that many would benefit from it.

Background

This article isn’t about an introduction to JavaScript arrays but more of studying the newly added functions of the Array object. I do suggest that you make a Google search if you are a beginner. Moreover, in my opinion, these added functions do have an aim. And, one of those is to make our lives easier and be productive when working with the Array object. Lastly, if you have a good understanding of arrays, you’ll be comfortable reading this article.

ECMAScript 6 Enhanced Arrays

As we have mentioned, the ECMAScript 6 (ES6) has added new methods to the global Array object. Thereby, will be discussing the following methods:

  • Array.from()
  • Array.of()
  • copyWithin()
  • fill()
  • find()
  • findIndex()
  • entries()
  • keys()
  • values()

During the 1st version of this article, the following methods: entries, values, and keys weren’t included. As a result, I decided to include them as of the 3rd of October 2020.

So let’s get started then. I hope you are excited.

The Array.from() Method

This is a static method that returns a new Array instance from an iterable object. However, you can also pass an “Array-like Object” in the first parameter. If you have no idea about it yet, it will be discussed as part of this section.

Syntax

//syntax 
//Array.from(arrayLike[, mapFn[, thisArg]]);

Parameters

  1. arrayLike – is the reference of an iterable object.
  2. mapFn – is optional, and acts as a callback known as map-function.
  3. thisArg – is optional too, and is the value of this inside the map-function.

Let us see an example below.

let result = 
Array.from('JavaScript', (val, indx) => `[${indx}]` + "=>" + val.toUpperCase());

console.log(result);

Output

As you can see, the example above is easy to follow.

Map Function

  • This is the 2nd parameter, if provided, it will act as a mapping callback when invoked. And, it transforms each value from the source to the returned target.
  • This is similar to Array.prototype.map() method.

Now, why not see another example don’t you think? And, why not put the Array.from() inside an Object. Thereby, we can see how the mapping callback function and the 3rd parameter this behaves.

const manager = {
  isBadManager: true,
  doBadStuff: function (items) {
    return Array.from(items, function (val, indx) {

      if (this.isBadManager) {
        console.log(`${indx + 1}. ${val[0].toUpperCase()}${val.substr(1)}`);
      }
    }, this);
  }
}

/**
 * Output:
 *  1. That's my idea
 *  2. Micromanage
 */
manager.doBadStuff(['that\'s my idea','micromanage']);

Again, easy to follow example. Now, let’s take it up a notch. And, let’s focus a bit more on the 1st parameter of the Array.map() which is the array-like object (arrayLike).

What is an Array-like Object?

Usually, you’ll experience some objects in JavaScript that looks like an array, commonly known as “Array-like Object”. Confused? Don’t be. It is an object which has a length property of a non-negative integer and it got some indexed properties.

Let us see an example below.

let arrLike1 = {
  length: 3,
  0: "Jin",
  1: "Vincent",
  2: "Necesario"
};

That’s it? Yes!

Now, let’s look at how we can convert the arrLike1 variable into a real array using Array.from().

let resultArray2 = Array.from(arrLike1);

console.log(resultArray2); 
//output: ["Jin", "Vincent", "Necesario"]

NodeList

A NodeList is another example of an array-like object. Even I struggled with NodeList. I thought it was an array but it is not.

NodeList and Arrays are completely different things.

OK, so what’s a NodeList? A NodeList object is a collection of DOM nodes that was extracted from the HTML document when using a browser API such as querySelector() and/or querySelectorAll().

Now, that we have an idea of what a NodeList is.

Let’s try to convert a NodeList to an Array with the use of Array.from().

<!-- this is the html file -->
<body>
    <div>
        <p>Hello World 1</p>
        <p>Hello World 2</p>
        <p>Hello World 3</p>
    </div>
</body>
/**
 * Start of NodeList
 * In this code sample we will see what a NodeList is. 
 * Here are some facts about NodeList. 
 * 
 * 1. NodeList aren't arrays. 
 * 2. NodeList does have a length property
 * 3. NodeList does have indexed property
 * 4. Therefore, we can conclued that a NodeList does looks like
 *    an Array-like object.
 * 5. We can convert NodeList into an array with the use of Array.from()
 */
window.addEventListener("DOMContentLoaded", function (event) { 

  let elements = document.querySelectorAll("div p");

  console.log(elements); //output: NodeList(3) [p, p, p]

  //this proves that NodeList does have a length property
  console.log(elements.length) //output: 3

  console.log(typeof (elements)); //output: object
  
  //this proves that the return of querySelectorAll method is a NodeList
  console.log(elements instanceof NodeList); //output: true

  //this proves that NodeList aren't arrays
  console.log(elements instanceof Array); //output: false

  let arrayParagraphs = Array.from(elements);

  console.log(arrayParagraphs); //output: Array(3)

});
 /**
  * End of NodeList
  */

Output

Now, that we are familiar with the array-like object and we have seen how it to convert to a real array.

The next concept we need to understand is how to avoid empty slots.

Avoiding Empty Slots

Empty slots? What are they?

Basically, when you create an array to a certain length without specifying the values per index you’ll have an empty index also known as an empty slot.

Let us see an example below.

const arrWithEmptySlots = [];
arrWithEmptySlots.length = 5;
arrWithEmptySlots[0] = "Jin";

//output ["Jin", empty × 4]
console.log(arrWithEmptySlots);

Output

How can I check for empty slots?

We can use the in operator to check if the array has a key. Moreover, it returns a boolean value, false for empty slots but true for slots with value, including the undefined value.

Let us see an example below.

const arrWithEmptySlots = [];
arrWithEmptySlots.length = 3;
arrWithEmptySlots[0] = undefined;
arrWithEmptySlots[1] = "Jin";

console.log(0 in arrWithEmptySlots);//true
console.log(1 in arrWithEmptySlots);//true
console.log(2 in arrWithEmptySlots);//false
console.log(3 in arrWithEmptySlots);//false

/**
 * output:
 * 0
 * 1
 */
for (let slot in arrWithEmptySlots) {
  console.log(slot);
}

What’s this empty slot got to do with the Array.from() method?

If you wanted to produce an array initialized to a certain length without empty slots, Array.from() solves that.

Let us see an example below.

const arrayWithEmptySlots_2 = [];
arrayWithEmptySlots_2.length = 5;

const results = Array.from(arrayWithEmptySlots_2);

//output: [undefined, undefined, undefined, undefined, undefined]
console.log(results);

Before we move to the next section.

We can then conclude that Array.from() not only creates a new Array instance from an iterable object. It also accepts an “Array-like Object” that will be converted into a real Array and helps us to avoid empty slots.

The Array.of() Method

Mostly, everyone understands that an Array constructor is utilized to create Array objects. Moreover, Array.of() method comes in as an alternative to the Array constructor and we are going to see why, in this section.

Syntax

//syntax
//Array.of([]);

Parameters

  1. [] – elements used to create the array.

Let us see some examples below.

  • Create a new Array constructor and pass more than one argument.
let cars = new Array("Toyota", "Mitsubishi", "Nissan", "Honda");

//output: 4
console.log(cars.length); 
//output: Toyota Mitsubishi Nissan Honda
console.log(...cars); 

let customers = new Array({ name: "Jin" }, { name: "Vincent" }, { name: "Necesario" });

//output: 3
console.log(customers.length); 
//output: {name: "Jin"} {name: "Vincent"} {name: "Necesario"}
console.log(...customers); 

let luckyNumbers = new Array(23, 29, 32);

//output: 3
console.log(luckyNumbers.length);
//output: 23 29 32
console.log(...luckyNumbers);
  • Create a new Array constructor and pass one argument. And, let us see the glitch.
let car = new Array("Toyota");
//still works.
console.log(car); 

let customer = new Array({name: "Jin"})
 //still works.
console.log(customer);

let luckyNumber = new Array(23);
//glitch
//output: 23
//23 in length????
console.log(luckyNumber.length); 

//another glitch
//output:  [empty × 23]
console.log(luckyNumber); 

A Small Glitch?

Did you spot the difference? Let’s take for instance the luckyNumber variable, it resulted differently compare to the variables car and customer.

Remember that when you have passed one argument with a number value. It is creating an empty array with a length property equal to the number and produces empty slots based on the length property.

Is this a glitch? Maybe yes or maybe no. In order for us to avoid this issue, we can use the Array.of() method.

Let us see an example below.

let superLuckyNumber = Array.of(23);
console.log(superLuckyNumber); //output: [23]

Therefore the Array.of() method was introduced to resolve the issue.

Let me know your thoughts in the comment section. Thanks in advance.

The copyWithin() Method

The copyWithin() method is used to copy the sequence of values of the array to a different position in the array.

Syntax

//syntax
//[].copyWithin(target, start, end);

Parameters

  1. target – is the index where to copy elements.
  2. start – is optional, and this is the index position where to start copying from.
  3. end – is optional, and this is the index where to actually end copying elements.

If start index is negative, it’s treated as length of array plus start-index ([].length + start). Same as with end index ([].length + end).

Let us see an example below.

let presidents1 = ["Donald Trump", "Barack Obama", "George Bush", "Bill Clinton"];
let presidents2 =  ["George H. W. Bush", "Ronald Reagan", "Jimmy Carter", "General Ford"];

//let's copy to index 0 from index 1
//let's replace Donald Trump with Barack Obama
//output: ["Barack Obama", "George Bush", "Bill Clinton", "Bill Clinton"]
console.log(presidents1.copyWithin(0, 1));

//let's copy to index 1 from index 2
//let's replace Ronald Reagan with Jimmy Carter up to 3rd index. 
//Up to 2nd index only excluding 3rd index.
//output: ["George H. W. Bush", "Jimmy Carter", "Jimmy Carter", "General Ford"]
console.log(presidents2.copyWithin(1, 2, 3));

Easy to follow isn’t? Let’s move to the next section.

The fill() Method

The fill method actually fills (entirely or partially) all the elements of the Array from the start index to the end index with the given value. Moreover, the start and end index are optional; therefore if they are not provided then the entire Array is filled by the value you passed.

Syntax

//syntax
//[].fill(value, start, end);

Parameters

  1. value – the value to fill the array.
  2. start – optional, and is the start-index.
  3. end – optional, and is the end-index.

If you have seen the issue of the Array constructor. Likewise, we can use this method to set the values for all the empty slots of the array.

You can do this as long as your target is to initialize an array with defined length and with no empty slots.

Let us see an example below.

let arryLenOf5 = new Array(5).fill(undefined);

//output: (5)[undefined, undefined, undefined, undefined, undefined]
console.log(arryLenOf5);

let arryLenOf3 = new Array(3).fill(0);

//output: (3) [0, 0, 0]
console.log(arryLenOf3);

Let us see some examples again.

//fills the entire array
console.log([29, 23, 5, 26, 16, 21].fill(29)); 
//output: [29, 29, 29, 29, 29, 29]

//fills the entire array starting at index 1
console.log([29, 23, 5, 26, 16, 21].fill(30, 1)); 
//output: [29, 30, 30, 30, 30, 30]

//fills the entire array starting at index 1 and ends at 5th position.
console.log([29, 23, 5, 26, 16, 21].fill(31, 2, 5)); 
//output: [29, 23, 31, 31, 31, 21]

If start index is negative, it’s treated as length of array plus start-index ([].length + start). Same as with end index ([].length + end).

//fills the entire array starting at index ([].length -2) = 4th index.
console.log([29, 23, 5, 26, 16, 21].fill(31, -2)); 
//output: [29, 23, 5, 26, 31, 31]

//fills the entire array starting at [1] index ends to ([].length -2) = 4th position.
console.log([29, 23, 5, 26, 16, 21].fill(31, 1, -2)); 
//output: [29, 31, 31, 31, 16, 21]

Easy to follow isn’t? Let’s move to the next section.

The find() Method

Before we go in-depth with the find() method will step back a bit. And answer: “What it does really resolves?”.

Syntax

//syntax
//[].find(callback(element,index,array), thisArg);

Parameters

  1. callback – a callback function that executes on each value in the array.
  2. thisArg – is optional, Object to use as this inside the callback.

The indexOf Method

Usually, the first thing that comes to mind when searching for a value in an array has been the use of indexOf() method.

Let’s see an example below.

let nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];

console.log(nums.indexOf(9)); //output: 0;
console.log((nums.indexOf(7) !== -1)); //output: true
console.log((nums.indexOf("9") == 0)); //output: false
console.log((nums.indexOf("Jin Vincent Necesario") !== -1)); //output: false

However, sometimes programmers forgets that this method requires a strict comparison. In my opinion, that’s why they (programmers) uses the some() method.

The some() Method

This method works by invoking a function callback for each element until one returns a true or truthy value, and finally, it stops.

The benefit is you have control over the comparison of values not unlike the indexOf() method.

Let us see an example below.

let nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log(nums.some((num) => num == "9")); //output: true
console.log(nums.some((num) => num === "9")); //output: false

Now, the drawback of the some() method is you can only get the boolean values true or false, if a suitably matched value was found, but not what the actual value matched.

What find() Method resolves?

The find() method resolves that issue. It works like the some() method, except once the callback returns its value, the actual array value is returned.

Therefore, find() method returns an array element. Only, if it satisfies the provided the expression passed to the callback function. Otherwise, it returns undefined.

Let’s see an example below.

let nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log(nums.find((num) => num == "9")); //output: 9
console.log(nums.find((num) => num === "9"));//output: undefined

Why not another example with the complete parameters?

let num = 5;
let nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];
let result = nums.find(function (value, index, array) {

  //just shows the values to the console window.
  console.log(`The num[${index}] is equal to ${value} ${this}`);

  return value === parseInt(this);
}, num);

console.log(result); //output: 5

The findIndex() Method

This is almost similar to the find() method. However, it returns the index of the array element instead of the element itself.

Syntax

//syntax
//[].findIndex(callback(element,index,array), thisArg);

Parameters

  1. callback – a callback function that executes on each value in the array until the function returns true. Otherwise, undefined, which indicates that element wasn’t found.
  2. thisArg – is optional,

Going back to the indexOf() method, we have seen that’s there no control over its matching logic. Thus, findIndex() saves the day.

Let’s see an example below.

let num = 5;
let nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];
let result = nums.findIndex(function (value, index, array) {

  //just shows the values to the console window.
  console.log(`The num[${index}] is equal to ${value} ${this}`);

  return value === parseInt(this);
}, num);

console.log(result); //output: 4

Now, that we have a good background on the find() method and the similarities of find() and findIndex().

Let’s have another example, a customized search.

const houses = [
  { length: 22,  width: 288,  measurement: 'ft' },
  { length: 182, width: 532,  measurement: 'ft' },
  { length: 12,  width: 152,  measurement: 'ft' },
  { length: 20,  width: 30,   measurement: 'ft' },
  { length: 12,  width: 152,  measurement: 'ft' }];

let indexResult = houses.findIndex((house) => (house.length * house.width) === 600);

console.log(indexResult); //output: 3

When To Use find() and findIndex() Method?

  • Don’t treat findIndex() method just like on how we use the indexOf() method for comparison because we have the some() method that returns the boolean value we need.
  • Don’t use findIndex() method to get the matched value because that’s what the find() method for.
  • Use indexOf() method if you need strict match.
  • Use findIndex() if you need the index of a more customized match.

The entries() Method

This method returns an iterable object. Moreover, the actual returned object is an Array Iterator that contains key/value pairs for each index of the array.

Syntax

//syntax
//[].entries();

Let us see an example below.

let fruits = ['mango', 'apple', 'dragon fruit'];

//output: returns Array Iterator {}
console.log(fruits.entries());

/*
 Let us show the [key, value] pair
 */
let fruitEntries = fruits.entries();

/*
 Output: 
 [0, "mango"]
 [1, "apple"]
 [2, "dragon fruit"]
 */
for (let current of fruitEntries){
  console.log(current);
}

/*let us show the index and element of the fruits array
 Output:
 0 "mango"
 1 "apple"
 2 "dragon fruit"
*/ 
for(let [index, element] of fruits.entries()){
  console.log(index, element);
}

The keys() Method

This method is similar to entries() method. However , the object returned contains the keys for each index in the array.

Syntax

//syntax
//[].keys();
let fruits = ['mango', 'apple', 'dragon fruit'];

//output: Array Iterator {}
console.log(fruits.keys());

let fruitKeys = fruits.keys();

//output: 0 1 2
console.log(...fruitKeys);

The values() Method

This method behaves similarly to [].keys() and [].entries(). However, the difference, this method returns the value of each key in the array.

let fruits = ['mango', 'apple', 'dragon fruit'];

//output: Array Iterator {}
console.log(fruits.values());

let fruitKeys = fruits.values();

//output: "mango" "apple" "dragon fruit"
console.log(...fruitKeys);

Summary

In this post, we have learned the new Array methods of the JavaScript(ES6) language. Moreover, we have tackled how these methods work, why it’s added? And what issue/issues does it resolve? Overall, we have seen the history and benefits of these methods. I hope you have enjoyed this article, as I have enjoyed writing it. Stay tuned for more. Until next time, happy programming!

Please don’t forget to follow/subscribe, bookmark, like, and/or comment. Cheers! And Thank you!

History

  • 13th September, 2020: Posted publicly.
  • 3rd October, 2020: Added the following methods: entries(), values(), and keys() as part of the content.