JavaScript Gotchas

This just cost me and a colleague about an hour.

  var headers = mydiv.getElementsByTagName('h3');
  for (var i = 0; i < headers.length; i++) {
    // ...

When run, this wasn’t going inside the for loop at all (in IE; firefox worked). So we stuck in an alert to see what headers.length came out as. [object] apparently.

After much chasing around the houses, we looked closer at the original HTML:

  <h3 id='length'>Some Header</h3>

It’s a miracle that this worked at all in firefox. What was happening is that the length property of the headers collection was being shadowed by the element with an id of length. That’s happening because the collection is an HTMLCollection, and the JavaScript DOM bindings specify that you can also index by id into that collection. And because functions and properties share the same namespace in JavaScript, disaster ensues.

So the lesson to take away from all this is that you should take great care to avoid using id’s that are the same as existing method or property names. Eric Meyer found the same things some time ago: Reserved ID Values.

4 Comments to JavaScript Gotchas

  1. Mike Czepiel says:

    Granted you may lose some flexibility but it may be easier and arguably more concise to just use a foreach loop.

    Though that obviously doesn’t help you if you do need to determine the length, chances are it eliminates you ever caring about the length in a lot of instances.

  2. Eric: Thanks for the kind words. I’ll try and stick a trackback in. And yes, thank you for the great subtitle. 😉

    Mathieu: Yes, that would have worked. But it’s not the “common idiom”, so it would have just tripped up somebody else later on…

  3. Eric Meyer says:

    Wow—it makes sense that this would happen in IE (that is, it’s consistent with what we know of IE’s behavior), and yet I’d never have thought of it on my own. Fun! If you could trackback to my post, that would be cool, since it would help tie all these scattered bits of information together. If it doesn’t work for some reason, let me know and I’ll stick in a link.

    And, hey, your site’s subtitle seems awfully familiar…

  4. That’s why I prefer the following syntax:

    for( var i=0,currentHeader; currentHeader=headers[i]; i++ )
    // here be some amazing code