Eli Perelman

Comparing Against Typeof 'Undefined' Instead of Undefined

For the last several months I seem to be having a recurring argument over comparing variables against undefined in JavaScript. The argument usually starts over code like this:

1
2
3
4
5
var func = function(val) {
  if (val === undefined) {
    // do something
  }
};

because I want the code to look like this:

1
2
3
4
5
var func = function(val) {
  if (typeof val === 'undefined') {
    // do something
  }
};

which causes an argument which goes something like this:

Me: Why are you comparing against undefined? You DO know that third party code can inadvertently change the value of undefined, right?

Person: Of course, but my code is contained in a function which redefines undefined to undefined, so it’s all good?

Me: But that won’t work in the global scope.

Person: True, so while in the global scope, I use typeof val === 'undefined'.

Me: So now your code is inconsistent.

Person: But that’s the way the jQuery style guide says to do it…

And on it goes. In almost any book which speaks of coding conventions, it states that no matter which convention you decide to use, make sure that the convention is strictly adhered to so that code is more readable and maintenance is easier.

But now we have an interesting situation with the creators of the most popular JavaScript framework on earth advocating two different coding styles based solely on whether your code is contained in a function or not:

“Expected an identifier and instead saw ‘undefined’ (a reserved word).” - In jQuery we re-declare ‘undefined’ as we use it internally. Doing so prevents users from accidentally munging the name (assigning to undefined and messing up our tests) and also makes the undefined checks slightly faster.

  • Global Variables: typeof variable === “undefined”
  • Local Variables: variable === undefined
  • Properties: object.prop === undefined

Source: jQuery Core Style Guidelines

Now obviously they are correct in their first method of using typeof to make sure a variable is undefined, because the value of undefined can be changed at any time by any code since in legacy browsers the undefined variable is just that: a variable. ECMAScript 5 compatible browsers (and hence JavaScript running in “strict mode”) forces the undefined variable to be “read only”, although it does this silently (without throwing an error).

The problem is that they adopt a different convention within their own internal code by comparing directly against undefined because they have created their own “internal” undefined variable:

1
2
3
(function( window, undefined ) {
  // jQuery source
})(window);

By not passing a value to the second argument, it has effectively created its own copy of undefined, and can now go on their way to comparing against it directly.

The question arises: why have two different coding styles? They claim speed. Is that justified?

In running my own tests over at jsperf.com, it looks as though in some browsers comparing directly against undefined is a little faster but only marginally. What is interesting is that in Chrome comparing against the typeof value === 'undefined' test is waaaaaay faster than comparing directly value === undefined. If you don’t believe me head on over to jsperf.com and try it out.

So, since the speed difference is negligible in some browsers and in fast much slower in Chrome, is it worth maintaining two different coding conventions for a speed argument that isn’t really there? I say no. Consistency is much more important. But even the jQuery Core isn’t even perfectly consistent. Take a look at this line from the jQuery source for the .data method:

1
if ( typeof key === "undefined" ) {

They are type-checking instead of a direct comparison, in direct contrast with the style guidelines.

So this is my point: jQuery Core, please do away with checking directly against undefined. It is only marginally faster in some browsers, much slower in Chrome, and makes the source inconsistent.

Comments