Associative Arrays in JavaScript are a breed of their own. It is a side effect of the weak typing in JavaScript. To understand the issue, let’s walk through some examples:
The length property is not defined as it would be in a normal array:
var basicArray = new Array(); basicArray[0] = "Portland"; basicArray[1] = "Beaverton"; basicArray[2] = "Lake Oswego"; console.log(basicArray.length); // --> Outputs 3, as expected var associativeArray = new Array(); associativeArray['city'] = "Portland"; associativeArray['state'] = "Oregon"; associativeArray['country'] = "United States"; console.log(associativeArray.length); // --> Outputs 0 in Chrome, what the heck? // we can also access values through .property notation ?! console.log("City is: " + associativeArray['city']); console.log("City is: " + associativeArray.city); // outputs // --> City is: Portland // --> City is: Portland
What is going on here? I want my associative array and I want it now!
Well it turns out, that just isn’t going to happen (grumble…). Associative arrays in JavaScript are actually treated as Objects. Properties and methods can be assigned arbitrarily. In practice, the associativeArray variable declared above doesn’t make sense. It is correctly done this way:
var myObject = {}; // denotes an Object is being created myObject.city = "Portland"; myObject.state = "Oregon"; myObject.country = "United States"; console.log(myObject.length); // results in undefined console.log("City is: " + myObject['city']); console.log("City is: " + myObject.city); // outputs // --> City is: Portland // --> City is: Portland
Now that we know we are working with an Object we have to implement our own length function (but does that really even make sense?).
One way to get at the properties is to use a for/in loop:
for(property in myObject) { console.log(property + " = " + myObject[property]); } // outputs: // --> city = Portland // --> state = Oregon // --> country = United States
Introducing Object.keys():
A manual loop? That seems too low level to be missing from the API! It turns out there is the Object.keys([object]) method, but it is not supported in all browsers. This link covers recent browsers and what JavaScript methods are supported. As you can expect IE8 is at the back of the pack, with FF 3.5 and Safari 4 sightly ahead. It seems that Chrome, FF 4+, and IE9 do quite well on the list.
Object.keys(myObject); // --> ["city", "state", "country"] Object.keys(myObject).length // --> 3 // calling myObject.keys() results in: // --> Type Error: Object #<Object> has no method 'keys'
Another way to define an array:
While we are on the subject of arrays in JavaScript, it is good know there are two ways to define them. Using var x = []; will also declare an array. In JavaScript with [] you do not have the option of setting the initial size of the array. You can only set the value at index 0. Note how the lengths are different in the example below:
// with this setup, there is no way to set the length ahead of time var terseDeclaration = [5]; console.log(terseDeclaration[0]); // --> 5 console.log(terseDeclaration.length); // --> 1 // with Array() the length can be set up front var longDeclaration = new Array(5); console.log(longDeclaration[0]); // --> undefined console.log(longDeclaration.length); // --> 5
More thoughts:
JavaScript is, after all, an Object Oriented language. The commonly operated on ‘window’ and ‘document’ keywords are objects defined by the browser. Even to this day, most users of the language rarely approach JavaScript with Objects mind. That likely attributed to JavaScript’s primary use as a DOM manipulator and event handler. Projects like Node.js are changing that rapidly. JavaScript’s growth will only continue to accelerate given the expanding use of web technology, particularly on mobile devices. Backbone.js is another popular framework that is gaining traction I have been playing with lately.