TECHY360
Everything You Need To Know About Tech

This is why creating an array via map doesn’t work in JS

0 17

Case

For demonstration, suppose you need to create an array of numbers from 0 to 99. How can you do this? Here is one of the options:

const arr = [];
for (let i = 0; i < 100; i++) {
  arr[i] = i;
}

If you are similar to me, then when you see the traditional for loop in JavaScript, you cringe a bit. In fact, I have not written a traditional loop for several years due to higher-order functions such as forEachmapfilter and reduce.

You may not have tried functional Kool-aid programming yet, and you think that the above solution seems perfectly fine. Technically, this is so, but after you have tasted the magic of higher-order functions, you probably think, “There must be a better solution.”

My first reaction to this problem was: “I know! I will create an empty array with a length of 100 and map the indices to each element! “JavaScript allows you to create an empty array of length n using the Array constructor, for example:

const arr = Array(100);

Perfect, right? I have an array of length 100, so now I just need to map the index to each element.

const arr = Array(100).map((_, i) => i);
console.log(arr[0] === undefined);  // true

What the hell !? The first element of the array must be 0, but in fact, it is undefined!

Explanation

I need to make an important technical note to explain why this happened. Internally, JavaScript arrays are objects, and numbers are keys. For instance:

['a', 'b', 'c']

Related Posts
1 of 26

essentially equivalent to this object:

{
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
}

When you access an element with index 0 in an array, you really get access to an object whose key is 0. This is important because when you think of arrays as objects combined with how higher-order functions are implemented, the cause of our problem takes shape.

When you create a new array through the Array constructor, it creates a new array object with the length property set to the value you passed, but on the other hand, the object is a vacuum. There are no index keys in the object representation of the array.

{
  //no index keys!
  length: 100
}

You get undefined when you try to access the value of an array with index 0, but this does not mean that the value undefined is stored in index 0, because by default it should return undefined in JavaScript if you try to access the value of an object by a key that does not exist.

It so happened that higher-order functions map, reduce, filter, and forEach iterate over the index keys of an array object from 0 to length, but the callback is only executed if the key exists in the object. This explains why our callback is never called, and nothing happens when we call the map function in the array – there are no index keys in the array!

Decision

As you now know, we need an array whose internal representation contains a key for each number from 0 to length. The best way to do this is to apply the operator to expand the array into an empty array.

const arr = [...Array(100)].map((_, i) => i);

Expanding an array into an empty array result in an array filled with undefined for each index.

{
  0: undefined,
  1: undefined,
  2: undefined,
  ...
  99: undefined,
  length: 100
}

This is because the spread operator is simpler than the map function. It simply iterates over the array (or any iterable object) from 0 to length and creates a new index key in the enclosing array with the value returned from the extension array at the current index. Since JavaScript returns undefined from our expanding array for each of its indices (remember that it does this by default because it does not have an index key for this value), we get a new array, actually filled with index keys, and therefore we can apply map (and reduce, filter and forEach).

Conclusion

We discovered some representation of arrays that are internally represented as objects in Javascript, and we learned the best interesting way to create arrays of arbitrary length, filled with whatever values ​​you need.

Comments
Loading...

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More