Skip to main content
JavaScript the Good parts book next to Javascript the definitive guide book

Fun Facts about JavaScript Arrays

JavaScript has a lot of quirks and weird parts, some of these impact the daily work of the average web dev, while some of it belongs to the sort of dark arts, which's only practical application is to create tricky interview questions.

Nonetheless, it's worth knowing these oddities in a language.
Today I was thinking to cover some lesser known behaviors involving JavaScripts's arrays, so let's dive in.

Arrays are actually Objects

We know that curly braces ({}) stand for objects and square brackets ([]) stand for arrays, right?
Well it turns out that arrays are just a special kind of object. You can prove this by checking the type of an array.

Or an even better option is to log out an array in your browser's console and see that the [[Protype]] points to the built in Array object.

A screenshot of an Array prototype viewed in the console of the browser

Observe all the built in array methods you know and love being listed on the prototype object (the faded color signals that they are read-only).

If you want to know that some unknown piece of data is indeed an array, the easiest way is to use the isArray static method on the Array prototype.

Now when your accessing an item inside an array with the bracket notation (meaning myArray[0]), you are actually accessing a key of the object, but because object keys can't be integers, under the hood JS actually converts that number you put in between the brackets to a string. So actually myArray[0] and myArray["0"] would yield the same result.

Also note that dot notation won't work, so myArray.0 will fail just as trying to use dot notation to get the value of an object key that uses a "-" character or an integer.

Speaking of keys, - or as we call them in this case array indices - there's another odd behavior that a lot of people don't know about. Namely that if you set an item with an index that's bigger than the currently available last index, JS will "fill up" the items leading up to that index with empty values. Don't believe me? Try it for yourself!

Observe that all the 97 items between the indices 2 and 100 will give undefined.

I don't really know the exact reason why this is, but if I had to guess it has to do with something relating to the fact that under the hood, JavaScript engines store arrays in some other data structure.

The practical implication is that if you want to dynamically insert new items to an array you should always use the built in push method instead of the bracket notation if you want to be safe and keep the consistency of your indexes.

Arrays are stored by Reference

There's something that tips off beginners and sometimes even experienced programmers coming from other languages.

When trying to compare arrays that look the same you run into a surprise.

This seems odd…

In other programming languages this would be true. Say in PHP.

Or in Python.

So what's going on here? If you understand that arrays are actually objects, then this whole thing will make sense.

In JavaScript objects are stored by reference and not by value like primitive data types. So that means that even if the values (and keys) are the same, internally they are stored on a different chunk of memory, so when comparing them for equality they will always return false, unless you compare the same object reference with itself.

Now again this has a lot of real world implications. For instance if you just reassign an existing array to a new variable and then start mutating the values you are in for some surprises.

You would initially expect that you've only modified the copiedDogBreeds array, but as you can see our original array also got "Labradoodle" as its third item.

To fix this you'll need to make an actual copy of the object. One way is to use the slice array method without any arguments

Or better yet use the spread syntax!

But wait! There's more…

So you would think that the above examples create a totally new JavaScript array object, right? Wrong! Both of these methods only create a so-called shallow copy, which still shares the same underlying values of the source object.

Now the practical consequence of this is that if we modify any nested value then we will still overwrite the values in the original array.

The only way around this is to make a deep copy, which is - you guessed it - a totally new array object with no connection whatsoever to the original.
The easiest way to do this is to serialize it to a JSON string then parse it back into a JavaScript object.

Summary

In essence you need to remember that arrays in JavaScript are actually objects with the indices as their keys and as objects they are stored by reference.

I hope you've learned a thing or two while reading this, cause I sure did while writing it.