I ran into an odd behavior/bug with Internet Explorer today that I hadn’t noticed before in relation to global variable assignments. Check out the following code that fails for me in IE 8 both in compatibility and standards mode:

$(document).ready(function() {
    panelNewResource = $("#panelNewResource");
    panelRename = $("#panelRename");
    panelTranslate = $("#panelTranslate");
    panelRenameResourceSet = $("#panelRenameResourceSet");
    lstResourceIds = $("#lstResourceIds");

    if (lstResourceIds.get(0).options.length > 0)
        lstResourceIds.get(0).onchange();
});

This code blows up on each of the of the variable assignments. Can you spot why? Even without knowing what other code is in the page, this code should work. If the variable exists – it should be reassigned. If it doesn’t exist the variable should be declared – at global scope (window) – and allow assignment.

This code is supposed to set global jQuery references to several frequently used UI controls. This isn’t exactly a best practice as these variables aren’t declared explicitly, but this code works fine in every other browser and this is what effectively amounts single point startup code. Regardless I’m making the assumption that the variables will l be created at global scope on the window object (ie. window.panelNewResource).

The code breaks on the first line with an “Object doesn’t support this property or method”.

Trying to simplify the scenario and make sure it’s not jQuery that’s failing I assigned a new Object and ended up with the same result:

IE8bug

But here is where this gets really weird: The problem occurs only on variable names that match document ids. My page has an element with an ID of panelNewResource and this is blowing up. If I rename the variable to panelNewResourceId for example and run the same code it works just fine.

Opening up the watch window (in IE 8’s native debugger which is a nice enhancement) on panelNewResource shows what’s going on:

idReference

IE is actually creating a global object that matches the item’s ID!

A quick check into older version of IE seems to confirm that IE has always had this behavior – IE creates matching elements for all DOM elements on the page based on its id. I can’t believe I’ve never noticed this before – although I’m pretty sure I’ve probably run into this problem before :-} .

What’s even weirder though is why this assignment fails. Ok so there’s a reference to the DOM element, but since it’s a variable why can’t it be assigned and effectively overwrite the DOM reference? It turns out it’s because there’s some whacky scoping going on with these DOM elements – presumably it’s an accessor that can’t be assigned to.

This issue probably also accounts for the large number of script errors that pop up on various sites when browsing with IE with a script debugger enabled. This explains at least a few that I’ve investigated on my own or other sites where object not found errors seemingly would be valid but failed. This is an easy thing to miss especially if like me you have no idea about this funky behavior.

The fix for this is easy enough: Simply change the name of the variables so they don’t conflict with ID names, or - probably the better choice – properly predeclare your variables up front which is what I did for my code:

var localRes = null;
var panelNewResource;
var panelRename;
var panelTranslate;
var panelRenameResourceSet;
var lstResourceIds;

$(document).ready(function() {
    panelNewResource = $("#panelNewResource");
    panelRename = $("#panelRename");
    panelTranslate = $("#panelTranslate");
    panelRenameResourceSet = $("#panelRenameResourceSet");
    lstResourceIds = $("#lstResourceIds");

    if (lstResourceIds.get(0).options.length > 0)
        lstResourceIds.get(0).onchange();
});

Problem solved, but this just another lame ‘feature’ Microsoft included in IE. In theory the feature is not bad – having a global ref for any ID on the page is somewhat handy, except for the fact that there can be naming conflicts and of course the whole fact that it doesn’t work in any other browser.

I really wish IE would just go away. Die a quick death and start over Microsoft. Seriously. After all the talk this week at MIX how Microsoft cares about Web developer experience to see even ‘standards’ mode IE perpetuate proprietary inconsistencies like this are just lame.