Wednesday, January 03, 2007

Associative Arrays in JavaScript

Some developers misuse the Array constructor to create an associative array. However, this is not a good way of doing this as all the methods/properties available to an array (length, index, sort etc) will not work.

var foo = []; // [] is the same as 'new Array()'
foo["bar"] = "baz";
alert(foo.length);

When the alert fires, it will return '0' instead of '1'.

As it doesn't function as a proper array, you may as well use an object instead:

var foo = {}; // {} is the same as 'new Object()'
foo["bar"] = "baz";

However, you can't see how many items there are without looping through the object. I have written a simple class that can be used that offers this (through the function 'getSize()' as well as a few other methods). As a result, you can't have anything with the keys 'getSize', 'remove', 'toString' and 'toArray'.

var AssociativeArray = function()
{
 if(arguments.length == 1 && arguments[0].constructor == Object)
 {
  for(var item in arguments[0])
  {
   this[item] = arguments[0][item];
  }
 }
 this.getSize = function()
 {
  var length = 0;
  for(var item in this)
  {
   if(item in new this.constructor === false)
   {
    length++;
   }
  }
  return length;
 }
 this.remove = function(item)
 {
  if(item in new this.constructor === false)
  {
   delete this[item];
  }
 }
 this.toString = function()
 {
  return this.toArray().toString();
 }
 this.toArray = function()
 {
  var output = [];
  for(var item in this)
  {
   if(item in new this.constructor === false)
   {
    output[output.length] = item + "=" + this[item];
   }
  }
  return output;
 }
}

To use this is pretty simple:

var foo = new AssociativeArray();
foo["one"] = 1;
foo["two"] = new Date();
foo["three"] = "A string";
// the above can also be done like this:
// var foo = new AssociativeArray({"one":1,"two":new Date(),"three":"A string"});
alert(foo); // alerts a comma separated string containing the items added
alert(foo.getSize()); // alerts the size (i.e. 3)
foo.remove("one"); // remove item 'one'
alert(foo.getSize()); // alerts the new size (i.e. 2)
var ar = foo.toArray().sort(); // sorted array (by key)

No comments: