Common pitfalls when working with Javascript Arrays

In most programming languages, an array is a data structure represented by an arrangement of items at equally spaced addresses in computer memory. Unfortunately, that is not the case with Javascript. A Javascript array is simply an object with array like characteristics reflected through certain methods.

Apart from being much slower than regular arrays, they can be quite problematic when misused. I will be summarizing some of the pitfalls that I have come across, along with tips to avoid them.

Length

The length of an array is computed as the largest integer property in the object plus one, and that is not necessarily the number of objects in the array! Lets take a simple example:


var myArray = [];
console.log(myArray.length); // outputs 0
myArray[100] = 'some value';
console.log(myArray.length); // outputs 101 despite containing one element

That is why it is advised to use Array.prototype.push for all insertions and refrain from explicitly setting index values. The push method will insert the value with the right key/index.

Removing elements

The delete operator can be used to remove a property from any object. Arrays are objects so if we apply that we'll end up with a hole in the array as the indexes(keys) will not shift automatically to reflect that change. Example:


var myArray = ['a', 'b', 'c', 'd'];
delete myArray[1];
console.log(myArray[1]); // outputs undefined while the expected value was c

Bottom line, using delete on arrays should be avoided.

The proper method for removing an element on a certain index would be Array.prototype.splice Other safe methods worth mentioning: Array.prototype.pop - add/remove elements from the end of the array Array.prototype.shift - add/remove elements from the beginning of the array

Sorting

Array.prototype.sort() is the go to method for sorting arrays, but there are a couple of issues we need to be aware of.

The sorting order is by default lexicographic and not numeric regardless of the types of values in the array. Even if the array is all numbers, all values will be converted to string and sorted lexicographically. Here is an example:


var myarray = [80, 9, 34, 23, 5, 1];
myarray.sort();
console.log(myarray); // outputs: [1, 23, 34, 5, 80, 9] 

While the correct output for the above should be [1, 5, 9, 23, 34, 80]

Fortunately, the sort method takes an optional compare function in order to specify the sort order. When the compare function is supplied no type will take place. The order depends on the return value of the compare function. To learn more about the rules I suggest checking out the description of compareFunction on MDN

Back to our last example, the proper way to sort an array of numbers would be:


myarray.sort(function(a, b){
    if (a < b)
        return -1;
    if (a > b)
        return 1;
    else
        return 0;
});

Type Checking

Javascript's typeof operator does not distinguish between an array and any other object.


console.log(typeof []); // outputs: object
console.log(typeof {}); // outputs: object

In order to identify an array type there are a couple of ways. One thing we can do is check Object.prototype.constructor method which returns a reference to the object function that created the instance's prototype.


function check_array (value) {
    return value && typeof value === 'object' && value.constructor === Array;
}

console.log(check_array([])); // outputs: true
console.log(check_array({})); // outputs: false

Another would be through applying Object.prototype.toString method to get the class.


function check_array (value) {
    return Object.prototype.toString.apply(value) === '[object Array]';
}

console.log(check_array([])); // outputs: true
console.log(check_array({})); // outputs: false

for-in loops

The for-in loop seems convenient at times but it is meant to iterate over an object properties rather than an array structure. There are two main reasons for that:

It does not guarantee order

The use of for-in makes no guarantee over the order of the properties. The order of enumeration depends on the implementation which might differ between browsers. According to this article, all modern implementations iterate through object properties in the order in which they were defined.

Unexpected properties from the prototype chain

for-in does not only iterate over properties attached to the object itself but also over its prototypes, and that might result in extra unexpected results. Here is an example


// Somewhere else in our program we decided to add an extra property for all arrays
Array.prototype.foo = "bar";

var myArray = [1,2,3];
var result = [];

for (var key in myArray){
    console.log(key);
}

// Outputs:
// 0
// 1
// 2
// foo

In the above example, foo becomes part of every array and will show up in a for-in. This can be avoided by checking that property does not belong to the prototype of the object on each iteration via hasOwnProperty, but is all that worth it?

And thats why it is advised to stick with the conventional for statement in order to avoid those problems. As long as the indexes of the array are correct it should work fine.

The associative array confusion

Associative arrays similar to those existing in other languages such as PHP do not exist in Javascript. An example such as this would "work" but is not correct:


var myAssocArray = [];
myAssocArray["foo"] = "bar";

The above example is not an associative array but rather an abused array object. The above code works simply because arrays are objects too. As a matter of fact the same thing can be applied to any other object in Javascript. myAssocArray["foo"] = "bar" is equivalent to myAssocArray.foo = "bar", simply adding a new property to the current array object.

For a key/value pairs structure using vanilla Javascript objects is the right option.

Did I miss anything?

I hope you enjoyed this post and found it useful in one way or another. If you think I missed anything, please let me know in the comments. Have a good day!

↑ Back to top
Fork me on GitHub