Best of Modern JavaScript — Array Holes and Operations

aumayeung profile image John Au-Yeung Originally published at thewebdev.info on ・3 min read

Subscribe to my email list now at http://jauyeung.net/subscribe/

Follow me on Twitter at https://twitter.com/AuMayeung

Many more articles at https://medium.com/@hohanga

Even more articles at http://thewebdev.info/

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at some array operations with holes.

Array Operations and Holes

Various operations treat array holes differently.

Iteration is done with the Array.prototype[Symbol.iterator] call.

It treats holes as if the entry is undefined .

We can see this if we call Symbol.iterator directly.

For instance, we can write:

const arr = [, 'foo'];
const iter = arr[Symbol.iterator]();


We return the iterator from to let us get the elements of the array sequentially with an iterator.

If we call next the first time, we get:

{ value: undefined, done: false }

And if we call next again, we get:

{ value: "foo", done: false }

As we can see, the value is undefined is returned from the first next call.

The spread operator also treats holes the same way.

For instance, we can write:

const arr = [, 'foo'];

After we spread the arr array, we can see the logged value is:

[undefined, "foo"]

The for-of loop also treats holes the same way.

For instance, if we write:

const arr = [, 'foo'];

for (const x of arr) {

then we get undefined and 'foo' .

Array.from() uses iteration to convert an iterable object to an array.

This works exactly like the spread operator.

For instance, if we have:

const arr = [, 'foo'];


Then we get:

[undefined, "foo"]

If we pass in an array-like object that isn’t iterable into the Array.from method, the missing entry is still treated as undefined .

If we have:

const arr = Array.from({
  1: 'foo',
  length: 2

then we get the same result.

With a second argument, Array.from works like Array.prototype.map .

For example, if we write:

const arr = Array.from([, 'foo'], x => x)


Then arr is [undefined, “foo”] .

We can also use it to get the index. To do that, we write:

const arr = Array.from([, 'foo'], (x, i) => i)

then arr is [0, 1] .

Array.prototype.map skip holes, but preserve them.

For instance, if we have:

const arr = [, 'foo'].map(x => x)


Then we get:

[empty, "foo"]

The hole stays as an empty slot after mapping.

It acts the same way if we map an array with holes to an array of indexes.

If we write:

const arr = [, 'foo'].map((x, i) => i)

we get [empty, 1] .

The behavior of array holes is treated differently by different array instance methods.

forEacg , filter , and some ignore holes.

map skips but preserves holes.

join and toString treat holes like they’re undefined ,

null and undefined are treated as empty strings.

copyWithin creates a hole when copying holes.

entries , keys , values, find, and findIndex treat each hole as if they’re undefined .

fill doesn’t care whether there are holes or not.

concat , map , push , reverse , slice , sort , splice and unshift all preserve holes.

pop and shift treat them as elements.


Different operators and methods treat array holes differently.

The post Best of Modern JavaScript — Array Holes and Operations appeared first on The Web Dev.

Posted on by:

aumayeung profile

John Au-Yeung


I'm web developer interested in JavaScript stuff.


markdown guide