console.log method (among others). And because I’m dealing with totally fabricated data, I’m using totally fabricated variable names too, to keep things simple. Well, I thought it would be simple.
Normally, I try to avoid using
try...catch statements, but in this particular instance, I was troubleshooting some issues with
console.assert in Opera 11, and the
try...catch statement was the only thing keeping me from going insane. Either way, the code inside the
try block wasn’t throwing an exception in Internet Explorer.
Anyways, after I completed my tests in Opera, I came back to Internet Explorer to work on a few other things, and noticed that in all the logs, the
e object was undefined instead of the object I expected. Since my code had evolved organically, and was quite a bit more complex than this example, and I couldn’t remember if it had ever fully worked (I thought it had, but I wasn’t sure), I embarked on a 30-minute long debugging excursion where I systematically removed and tweaked code from the project until I had pretty much nothing left, at which I finally decided to take another look at the example code to see if anything was out-of-place there.
That’s when I finally noticed that the
catch block I had just recently added had an argument
e that just happened to coincide with the object variable
e that was all-of-a-sudden logging as
So, last night, I tweeted a little joke, “I may have just discovered another way to test for IE…
In the interests of being thorough, I tested this quirky behavior in Firefox 2-4, Chrome 8-10, Safari 3-5, Opera 9.6-11 and IE 6-9, and have only seen this behavior in Internet Explorer 6-8. I haven’t tested in any mobile browsers. You can load my simple test page (which is a combination of the two following examples) in any browser, and if you see
1,1,2,1,1,2, things are working as-expected. If you see something like
1,,1,[object Error],[object Error],[object Error], you’re probably in Internet Explorer 6-8.
In the following test, the
try...catch statements have simply been defined, and since there’s no code inside of them, no exceptions will be thrown. Notice how, in Internet Explorer 6-8, the mere act of specifying a
catch clause ( with a named argument,
e) appears to implicitly declare that argument in the current scope, as if
var e was specified.
In the following test, the
try...catch statements contain code that will throw an exception of type
ReferenceError, because an attempt is made to access an undeclared variable. Notice that in Internet Explorer 6-8, not only does the
catch clause argument get implicitly declared (like in the previous example), but its value is set to the exception object, overriding any previously-set value.
It’s like a whole new kind of hoisting, made extra-special just for Internet Explorer 6-8. Except that you had no idea it was happening.
So, what’s the solution? Use a unique variable name in your
catch blocks. Tell people to “pretty please, use a better browser.” Maybe pay more attention when debugging, or just try to get more sleep, in general. That’s all I’ve got. And I’m not sure what else I can say about this specific “
catch argument declaration/leakage” issue, other than that I haven’t yet seen it documented anywhere, so I hope this article helps somebody, somewhere.
Also, FWIW, if you try to do what I’ve done in my examples, JSLint will yell at you, saying “Do not assign to the exception parameter.” It won’t explain why, nor will it tell you that the current scope has become tainted with a brand new named variable in Internet Explorer 6-8, or that even if you’re not assigning it, its value may have changed, but at least it gives you some kind of warning, which may be helpful.