Main navigation

Javascript: Understanding Objects vs Arrays and When to Use Them. [Part 2]

In Part 1 of this blog post I omitted one very important detail about the nature of Arrays. You might have heard this already: "Everything is an Object in javascript!". This is technically true. While String, Bool and Number are literals, javascript silently creates a wrapper Object around the primitive at the time of access. There are couple of other special data types that are not Objects (i.e. Undefined and Null), but for the most part you will be dealing with "things" that inherit from the Object prototype. Arrays and Functions also inherit from Object via prototype chain. As the matter of a fact, functions are first class Objects and can be passed as arguments to other functions or even be returned by another function. If you haven't worked with other lambda-like languages, anonymous functions and functions as first class citizens might look weird at a first glance. However, this is a very powerful concept and one of aspects of the language that makes javascript as powerful and fun to work with. But enough about functions, I will leave that topic for another time. What you need to keep in mind is that Array is inheriting from Object. I will explain why this matters in a minute.

This brings us to:

Iteration

Array(s):

If you are coming from languages like Java and PHP, you might want to do something like this:

This resembles for-each loop in PHP/Java and I have seen it used to iterate arrays in javascript way too often. What is even more frustrating is that the example above appears to be working, until it isn't. As mentioned above, Arrays inherit from Object via prototype chain. This becomes important when iterating arrays as we can see in the slightly modified example:

So what exactly happened here? We never added "bar" to myArray, so why in the world would it show up in sum?
For-in loop in javascript iterates through any enumerable property on the instance and its prototype chain. In this case, for-in loop will iterate through each index in the array, then move onto its prototype (i.e. Object) which has enumerable property 'foo'. There are ways to mitigate this, but instead of fighting our tools we should use standard for loop:

It is important to note that above output was in order by accident. Unlike indexed Arrays, Object properties are iterated in arbitrary order and you shouldn't rely on them being in any particular order. Another thing to be aware of is that the loop will go through prototype chain and iterate through any other enumerable properties. I have found this to generally be a desired behavior as for the most part we use prototype chain inheritance to extend and/or decorate current Object. In case where you are interested only in properties for this instance only, you can do additional check within the loop:

To summarize, Arrays are really good at storing ordered lists and ordering things while the cost of removing/splicing elements is a bit higher. Objects are great at representing schemas and the cost of augmenting or deleting properties is very low, but are not good for preserving order. When working with JSON API endpoints that return list of items, you will generally be working with Arrays of Objects.

I hope you find this article helpful and if you have any questions or comments, I would love to hear from you.

I thought everything in JS is an object, besides strings, booleans, and a few others... Is an array not an object? Can you be kind enough to give me an indepth resource, i.e. book or very good article. Im not quite on par to understand this stuff but I do know quite a big of javascript.

Just to add to this, objects are not enumerated and need to have key value pairs. This means you won't be able to do var x = {[]}; This will throw a syntax error as we are expecting JS to implicitely associate value [] with some property, which it doesn't know how to do. The way we fix this is by being explicit about the property in our object that points to this array: var x = { something: [] };

I'm guessing it was just to make clear the difference between the two examples, by adding an extra line of code rather than altering an existing one. Your suggestion is neater in this case, although there is a typo: you shouldn't have the ! because the sense of the test needs to be reversed.