Skip to main content

Why does the mapping of an array built in JavaScript not work?

Stage

For the sake of demonstration, let's say you need to generate an array of numbers from 0 to 99. How could you do this? Here is an option:

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

If you're like me, seeing a traditional loop in JavaScript makes you a bit uncomfortable. In fact, I haven't written a traditional loop in years thanks to higher-order functions like map, filter, and reduce. Perhaps you have not had contact with functional programming and are thinking that the above solution seems to be perfectly fine. Technically it is, but after you've tried the magic of higher-order functions, you're probably thinking, "There must be a better way". My first reaction to this problem was: "I know! I will create an empty array of length 100 and map the indices of each element ». JavaScript allows you to create an empty array of length n with the array constructor, like this:

const arr = Array (100);

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

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

What happen!? The first element of the array should be 0, but it is actually undefined!

Explanation

There is an important technical distinction that I need to make here to explain why this happened. Internally, JavaScript arrays are objects, with numbers as keys. For example:

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

is essentially equivalent to this object:

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

When accessing the element at index 0 of an array, you are actually only accessing an object property whose key is 0. This is important because when you think of arrays as objects in conjunction with how these are implemented higher-order functions (don't worry, I did that part for you), the cause of our problem makes sense.

When a new array is created with the array constructor, a new array object is created with its length property set to the value you passed in, but otherwise the object is a void. 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 the array at index 0, but it is not that the undefined value is stored at index 0, it is that the default behavior in JavaScript is to return undefined if you try to access the value of an object for a key that does not exist.

It happens that higher-order functions map, reduce, filter and iterate over the index keys of the 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 on the array - there are no index keys!

Solution

As you already know, what we need is an array whose internal representation of objects contains a key for each number from 0 to length. The best way to do this is to spread the array into an empty array.

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

Spreading the array into an empty array results in an array that is filled with undefined elements at each index.

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

This is because the extent operator is simpler than the map function. It just loops the array (or any other iterable, really) from 0 to length and creates a new index key on the attached array with the value returned by the scatter array at the current index. Since JavaScript returns undefined information from our hash array in each of its indexes (remember that it does this by default because it doesn't have the index key for that value), we end up with a new array that is actually filled with keys of index and therefore mappable (and reducible, filterable, and fit for each).

conclusion

We discovered some of the implications of arrays being represented internally as objects in Javascript, and we learned the best way to create arbitrary length arrays filled with whatever value you need.

As always, you can continue browsing this website where you will find the best courses in JavaScript.