Javascript Gotchas

This page contains all the facts about Javascript that I wish I knew as I was learning Javascript. Generally Javascript is a very simple language, but there are a few dark corners where Javascript doesn't do quite what you would expect.

Map keys are Strings

Some Terminology: Some people call the objects, some call them associative arrays. I'm going to use the term map here, because we are using them as maps rather than objects in an O-O style.

Javascript only has a few built-in types (boolean, float, string, object, array) and it converts from one to another quite freely. So it is easy to think that the following code will create 2 entries in the map, however because all the keys are converted to strings, there is only one:

var a = 3 + 4; // a is the number 7
var b = "7";   // b is a string containing a number

var map = {};
map[a] = "entry 1";
map[b] = "entry 2";

alert(map[a]); // "entry 2"

An Object's attachment to a function is unrequited

In most O-O languages a method knows what object it is a member of. In Javascript, while objects are attached to functions, a function really doesn't care who it is being used by.

You'd be forgiven for thinking that the following code would display the result "1 2" (several times depending on the length of the array).

{
  // inside some method on an object
  var instance = "1";
  this.member = "2";
  array.sort(function(a1, a2) {
    alert(instance + " " + this.member);
    // ...
  });
}

In reality you'll get an error that this isn't what you think it is. Although objects know all about the functions they contain, the functions themselves don't care much for their parentage. So when you pass the function to the sort routine it forgets all about the object that it is a part of, and this becomes reverts to the window.

The solution is to use a variable that points at this as part of the closure.

{
  // inside some method on an object
  var instance = "1";
  this.member = "2";
  var cthis = this;
  array.sort(function(a1, a2) {
    alert(instance + " " + cthis.member);
    // ...
  });
}

And now the output will be "1 2" as expected. this has still been forgotten, but cthis is part of the closure so we can access this through it cthis.