Yesterday, there was an embarrassing JavaScript error in some piece of functionality in our product at work.

To make it even worse, it appeared I had authored the excact row where things broke. To make it even worse, it was where I had made a somewhat lame effort to be robust.

It was about trying to handle the second (optional) parameter to a function - an options object. Instead of some standard (sloppy) cast-to-boolean check:

options || (options = {}); // kinda works

, I had decided to to act like some kind of grown up or something and avoid traps in the form of true, " " and 1 etc., like so:

function foo(url, options) {
  // did we get any options object? if not, create an empty one
  "[object Object]" == ({}).toString.call(options) || (options = {});
  // append some parameter if it was given in options
  "undefined" == typeof options.id || (url += "&id"+options.id);
}

Besides the opportunity to use the ({}) construct, this would also prevent sending in stuff like strings/arrays/functions/etc. that could act like property holders.

Fine, except IE8 gives "[object Object]" for both null and undefined. Waaahhh…

Here’s a rundown of what ({)}.toString.call(o); produces for various values of the parameter o:

IE9+, FF, Chrome, Opera IE8-
void 0 [object Undefined] [object Object]
null [object Null] [object Object]
{} [object Object]
[] [object Array]
/foo/ [object RegExp]
new Date [object Date]
"foo" [object String]
true [object Boolean]
false [object Boolean]
function() {} [object Function]
NaN [object Number]
1 [object Number]
new Error("foo") [object Error]

This “class”-checking technique is generally quite useful, since it works with the language’s underlying type for the value. It also works across frames and such, unlike instanceof. Just beware of the described behaviour regarding null and undefined in IE8-.

More reading in this old post (don't skip the comments): http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/