A walkthrough of the different Array methods of ES6 discussing what it has to offer. Furthermore, we will answer: “Why these methods are added to the language and issues it resolves?”
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, we will be discussing the following methods:
Array.from()
Array.of()
copyWithin()
fill()
find()
findIndex()
entries()
keys()
values()
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
Parameters
arrayLike
– is the reference of an iterable object. mapFn
– is optional, and acts as a callback known as map-function. thisArg
– is optional too, and is the value of this
inside the map-function.
Example
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);
}
}
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 look 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);
NodeList
A NodeList
is another example of 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 what a NodeList
is, let’s try to convert a NodeList
to an Array
with the use of Array.from()
.
<!--
<body>
<div>
<p>Hello World 1</p>
<p>Hello World 2</p>
<p>Hello World 3</p>
</div>
</body>
window.addEventListener("DOMContentLoaded", function (event) {
let elements = document.querySelectorAll("div p");
console.log(elements);
console.log(elements.length)
console.log(typeof (elements));
console.log(elements instanceof NodeList);
console.log(elements instanceof Array);
let arrayParagraphs = Array.from(elements);
console.log(arrayParagraphs);
});
Output
Now that we are familiar with the array-like object and we have seen how to convert it 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";
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);
console.log(1 in arrWithEmptySlots);
console.log(2 in arrWithEmptySlots);
console.log(3 in arrWithEmptySlots);
for (let slot in arrWithEmptySlots) {
console.log(slot);
}
What’s this empty slot got to do with 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);
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
Parameters
[]
– 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");
console.log(cars.length);
console.log(...cars);
let customers = new Array({ name: "Jin" }, { name: "Vincent" }, { name: "Necesario" });
console.log(customers.length);
console.log(...customers);
let luckyNumbers = new Array(23, 29, 32);
console.log(luckyNumbers.length);
console.log(...luckyNumbers);
- Create a new
Array
constructor and pass one argument. And, let us see the glitch.
let car = new Array("Toyota");
console.log(car);
let customer = new Array({name: "Jin"})
console.log(customer);
let luckyNumber = new Array(23);
console.log(luckyNumber.length);
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);
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
Parameters
target
– the index where to copy elements start
– optional, this is the index position where to start copying from end
– optional, 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"];
console.log(presidents1.copyWithin(0, 1));
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
Parameters
value
– the value to fill the array start
– optional, and is the start-index 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);
console.log(arryLenOf5);
let arryLenOf3 = new Array(3).fill(0);
console.log(arryLenOf3);
Let us see some examples again:
console.log([29, 23, 5, 26, 16, 21].fill(29));
console.log([29, 23, 5, 26, 16, 21].fill(30, 1));
console.log([29, 23, 5, 26, 16, 21].fill(31, 2, 5));
If start index is negative, it’s treated as length of array plus start-index ([].length + start
). Same as with end index ([].length + end
).
console.log([29, 23, 5, 26, 16, 21].fill(31, -2));
console.log([29, 23, 5, 26, 16, 21].fill(31, 1, -2));
Easy to follow isn’t? Let’s move to the next section.
The find() Method
Before we go in-depth with the find()
method, we will step back a bit. And answer: “What does it really resolve?”
Syntax
Parameters
callback
– a callback function that executes on each value in the array thisArg
– is optional, Object
to use as this
inside the callback
The indexOf Method
Usually, the first thing 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));
console.log((nums.indexOf(7) !== -1));
console.log((nums.indexOf("9") == 0));
console.log((nums.indexOf("Jin Vincent Necesario") !== -1));
However, sometimes programmers forget 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"));
console.log(nums.some((num) => num === "9"));
Now, the drawback about 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 is 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"));
console.log(nums.find((num) => num === "9"));
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) {
console.log(`The num[${index}] is equal to ${value} ${this}`);
return value === parseInt(this);
}, num);
console.log(result);
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
Parameters
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. 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) {
console.log(`The num[${index}] is equal to ${value} ${this}`);
return value === parseInt(this);
}, num);
console.log(result);
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);
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 a 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
Let us see an example below.
let fruits = ['mango', 'apple', 'dragon fruit'];
console.log(fruits.entries());
let fruitEntries = fruits.entries();
for (let current of fruitEntries){
console.log(current);
}
for(let [index, element] of fruits.entries()){
console.log(index, element);
}
The keys() Method
This method is similar to the entries()
method. However, the object returned contains the keys for each index in the array.
Syntax
Let us see an example below.
let fruits = ['mango', 'apple', 'dragon fruit'];
console.log(fruits.keys());
let fruitKeys = fruits.keys();
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.
Syntax
[].values();
Let us see an example below.
let fruits = ['mango', 'apple', 'dragon fruit'];
console.log(fruits.values());
let fruitKeys = fruits.values();
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 it resolves? 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, bookmark, like, and/or comment. Cheers! And thank you for reading!
- 10th September 2020: Initial version
- 11th October 2020: Added the following:
entries()
, keys()
and values()