Arrays in Javascript: The Weird Parts

Like in many programming languages, Arrays are a very important part of Javascript. They group a number of elements into a single variable, allow access to these individual elements via their index, and can be iterated through with a loop.

But beyond the basics, arrays can sometimes behave in unexpected ways. Some of this behavior is actually common to many languages, and some of it is specific to Javascript, but in either case these things can trip up programmers and create bugs in software. The purpose of this post is to showcase and explain a number of these ‘weird parts’.

Arrays are Objects

In Javascript, every variable that you declare can be classified as either a primitive or an object. The list of primitive types are:

  • Boolean
  • Null
  • Undefined
  • Number
  • String

Notice that arrays are not on this list. This is because they are actually special objects. Check out the following pen to see for yourself:

1

This makes type checking for an array a bit tricky.Array.isArray() should be used to be safe:

1

 

Arrays Copy by Reference

The fact that arrays are not primitive types has further implications. While primitives copy by value, objects copy by reference. See the following example:

1

After checking the console you will see that the pets array and the newPets array is the same despite all the changes being made on the newPets array directly.

This is because when we made the assignment var newPets = pets we did not create a new array. Instead, a new variable was created that points to the same array in memory.

If we want to make an actual copy of  pets then we need to make a new array and add the elements from the old array. One shortcut to achieve this is the slice() method:

1

 

2D+ Arrays can be Tricky

Using slice() is a great way to copy 1D arrays, but what happens when using 2D arrays (an array of arrays)?

1

Once again, the operation will affect both arrays, although grid === newGrid is returning false. This is because although we have created a new memory address for newGrid, the elements that it contains still refer to the same memory address as the original! This is just a shallow copy, and in order to create a truly new array you need to perform a deep copy. Here is one way to do this:

1

In this example we know that grid is a 3×3 2D array so we can setup a simple nested loop. Recursion would be a better method if we didn’t know the size beforehand.

 

Array Equality

By this point we know that arrays are objects and that they copy by reference, not value. Given this, it should come as no surprise that equality operations can be tricky as well:

1

As a human, I can see that arr1 and arr2 are the same, but Javascript seemingly disagrees. This is because Javascript only cares about the memory address of the array, not the values and order of the elements it contains. Here are a few ways to check the array for equality in the way that you might have expected:

1

 

Beware of const

const is an ES6 spec keyword that, unlike var and let, is non mutable. Basically, this means that you cannot change it after it has been declared. This new (to Javascript) feature is useful because it gives protection to variables that should remain the same once they are declared. Technically speaking, const works for arrays in the same way that it does for any other value, but it is important to remember how arrays work to avoid unwanted surprises. Take a look at the following code:

1

As you can see, declaring an array as a const offers you no guarantee that the array will stay the same. Much like the above examples the key thing to remember is that the Javascript engine is looking at the array by its memory address (or pointer). Attempting to change this will result in an error, but performing operations on the array will not. For this reason scope management is still the best way to protect arrays despite new tools like the const becoming available.

Summary

The above examples show some of the common ‘Gotchas’ to using arrays with Javascript. Knowing how arrays work is critical because it will reduce the risk of creating bugs and support your debugging knowledge when they do get created. The next post that I plan to write will focus on functional operations and the nicer side of using arrays in Javascript.