JavaScript: Hitting Bottom #2 – FUNdefined

What better way to understand a language than to understand the basic types? And what can be more basic than `undefined`?

    /**
     * Undefined is generally well behaved.
     */
    test("FUNdefined", function() {
      equals(undefined > 0, false);
      equals(undefined < 0, false);
      equals(undefined >= 0, false);
      equals(undefined <= 0, false);
      equals(undefined == 0, false);
      equals(undefined === 0, false);
 
      equals(undefined == null, true);
      equals(undefined == false, false);
      equals(undefined == true, false);
 
      equals(undefined === null, false);
      equals(undefined === false, false);
      equals(undefined === true, false);
 
      equals(undefined == undefined, true);
      equals(undefined >= undefined, false, "!");
      equals(undefined <= undefined, false, "!");
    });

Pretty much no surprises there. The only thing to watch out for is that `(undefined >= undefined) == false` which makes some sense mathematically, but it might make more sense for it to equal `undefined`.

But where’s the FUN? I wouldn’t have a reputation as a professional ranter about JavaScript if I didn’t rant about JavaScript…

    /**
     * null is pretty weird. It's almost like zero but not equal to false.
     */
    test("null", function() {
      equals(null > 0, false);
      equals(null < 0, false);
      equals(null == 0, false);
      equals(null >= 0, true, "!!!");
      equals(null <= 0, true, "!!!");
      equals(null === 0, false);
 
      equals(null == false, false, "!!");
      equals(null >= false, true, "!!!");
      equals(null <= false, true, "!!!");
 
      equals(null > true, false);
      equals(null < true, true, "!!!");
      equals(null == true, false);
      equals(null >= true, false);
      equals(null <= true, true, "!!!");
 
      equals(null == undefined, true);
      equals(null >= undefined, false, "!");
      equals(null <= undefined, false, "!");
 
      equals(null == null, true);
      equals(null >= null, true);
      equals(null <= null, true);
    });

Legend

  • “!”: “note this!”
  • “!!”: ‘hmm… strange.”
  • “!!!”: “WTF!?!?!”

This set of tests for the behavior of null has a ratio of 22/20 !s/line. That means that there is significant unexpected behavior around `null`. The `undefined` exploratory test only had 2/15 !s/line, much less crazy. Let me repeat the most insane part:

      equals(null == false, false, "!!");
      equals(null >= false, true, "!!!");
      equals(null <= false, true, "!!!");

I’ve basically given up on comprehension of this particular behavior and just settled for explanation and documentation instead.

So, what’s the point? Am I just picking on poor little old JavaScript? Partly, but my real aim is to document the myriad of strange and tantalizing (and infuriating) edge cases.

The moral of the story is to return `undefined` from methods where the result may be involved in a numeric comparison rather than null. Additionally `undefined` is the result returned by the empty function:

    equals((function(){})() === undefined, true);

so it’s more natural. The other recommendation is to always use the strict equality operator, it cuts out the most common weird edge cases. Tools like JSLint will point out situations where some subtle bugs can arise, use them!

The roller-coaster whirlwind-tour continues tomorrow with “The Crucible of Truthiness”. Stay tuned!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>