What are Holes in Arrays?
Tags: javascript, webdev, programming, beginners
Published: 2021-01-23 01:58:21

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

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

One special feature of JavaScript arrays is that not every slot in the array has to be filled with values. This means that we can skip values as follows:

```
let arr = [];  
arr[1] = 1;  
arr[10] = 10;
```

We don’t have to worry about setting values for other slots of the array.

There’s also an alternative syntax for doing the above, by writing:

```
[, 1, , 2];
```

What we have above are called _holes of an array_, where we have nothing between the commas. An array with holes is called a _sparse array_.

In this piece, we’ll look at how holes in arrays are handled in JavaScript.

* * *

Checking for Values in Arrays
=============================

We can check for holes in arrays with the `in` operator. To do this, we can write something like the following code:

```
const arr = [, 1, , 2];  
1 in arr;
```

We should get `true` returned from the last line since 1 is in the array.

ES6 treat holes in arrays as `undefined` entries. So if we want to check for holes in the array, check for `undefined`.

Iterators and generators also treat holes as `undefined`. For example, if we have

```
const arr = [, 1, , 2];  
const iter = arr[Symbol.iterator]()

for (let a of iter) {  
  console.log(a);  
}
```

we get

```
undefined  
1  
undefined  
2
```

If we call `next` to get the next item, as follows,

```
iter.next();
```

we get

```
{value: undefined, done: false}
```

for the first entry.

Likewise, if we have the given generator,

```
function* generator () {  
  const arr = [, 1, , 2];  
  for (let a of arr) {  
    yield a;  
  }  
}

for (let a of generator()) {  
  console.log(a);  
}
```

we get the same thing.

* * *

Array.from()
============

`Array.from()` treats holes as `undefined` like with iterators and generators.

For example, if we have

```
const arr = [, 1, , 2];  
const arrFrom = Array.from(arr);
```

then we get that the value of `arrFrom` is

```
[undefined, 1, undefined, 2]
```

Likewise, if we create an array from array-like objects, where we have non-negative integers as keys and a length property with a non-negative number as a value, missing entries are also treated as `undefined`.

For example, if we run

```
const arrFrom = Array.from({  
  1: 'foo',  
  length: 2  
});
```

we get the value of `arrFrom` as

```
[undefined, "foo"]
```

* * *

How Array.prototype Methods Treat Holes
=======================================

The behavior of these methods differs with different versions of JavaScript. In ES5, they’re the following:

*   `forEach`, `filter`, `every`, and `some` ignore holes.
*   `map` skips but preserves holes.
*   `join` and `toString` treat holes as if they were `undefined` elements but treat both `null` and `undefined` as empty strings.

The following is a full list of methods and how they deal with holes. Each method acts differently.

*   `concat` — keeps holes
*   `copyWithin` — holes are copied
*   `entries`, `keys`, `values` — treats holes as `undefined`
*   `every` — ignores holes
*   `fill` — fills holes
*   `filter` — removes holes
*   `find` — treats holes as elements
*   `findIndex` — treats holes as elements
*   `forEach` — ignores holes
*   `indexOf` — ignores holes
*   `join` — converts holes to empty strings
*   `lastIndexOf` — ignores holes
*   `map` — preserves holes
*   `pop` — treat holes as elements
*   `push` — preserves holes
*   `reduce` , `reduceRight`— ignores holes
*   `reverse` — preserves holes
*   `shift` — treat holes as `undefined`
*   `slice` — preserves holes
*   `sort` — preserves holes
*   `toString` — preserves holes
*   `unshift` — preserves holes
*   `values` — converts holes to `undefined`

When arrays are sparse, they have holes. They’re iterated through as `undefined`, but each array prototype method treats holes differently, so we have to be careful when defining arrays with holes and dealing with them.

We can use the `in` operator to check if a given entry is in an array.

`Array.from()` also treats holes as `undefined` and turns holes into `undefined` when converting arrays or array-like objects with holes into arrays.