What Type?

12 Apr 2010 | By Alex Young | Tags javascript tutorials

Whilst reading Object-to-Primitive Conversions in JavaScript, I wondered: what’s a good way of checking types in JavaScript? A lot of my work reflects on properties to detect capabilities, so I thought it was an interesting question.

Given that Objects have a constructor property, I dimly remembered that I’d seen this used somewhere to detect types. In fact, it’s pretty obvious that this is a good way to check for type programatically:

[1, 2, 3].constructor === Array
// true
[1, 2, 3].constructor === Number
// false

Certain types aren’t objects though, because JavaScript does have built-in types that behave differently. Section 8 of ECMA-262 lists each of the types:

  1. Undefined
  2. Null
  3. Boolean
  4. String
  5. Number
  6. Object

As we’ve previously seen on DailyJS, using typeof on these types can yield unintuitive results. A type checking algorithm should be aware of this to filter out special cases for undefined and null.

After half-an-hour of experimenting I wrote this:

(function() {
  function isNull(obj, type) {
    return obj === null && type === null;
  }

  function isUndefined(obj, type) {
    return typeof obj === 'undefined' && obj === type;
  }

  function matchesConstructor(obj, type) {
    return obj.constructor === type;
  }

  isType = function(obj, type) {
    if (isUndefined(obj, type)) {
      return true;
    } else if (isNull(obj, type)) {
      return true;
    } else if (matchesConstructor(obj, type)) {
      return true;
    }
    return false;
  }
})();

I wrote some tests as I was developing it and it seems to hold up fairly well. Check out the code and tests on GitHub: istype.js. The code is intentionally explicit to make it easy for beginners to follow.

Equality

I had a related problem when writing a unit testing library — what’s the best way of checking equality? Although this sounds simple, the solution is quite deep. It requires a solid understanding of the underlying types, objects and their behaviour. The best code I found was in another testing library, jspec:

 equal: function(a, b) {
   if (typeof a != typeof b) return
   if (a === b) return true
   if (a instanceof RegExp)
     return a.toString() === b.toString()
   if (a instanceof Date)
     return Number(a) === Number(b)
   if (typeof a != 'object') return
   if (a.length !== undefined)
     if (a.length !== b.length) return
     else
       for (var i = 0, len = a.length; i < len; ++i)
         if (!equal(a[i], b[i]))
           return
   for (var key in a)
     if (!equal(a[key], b[key]))
       return
   return true
 }

What I liked about this approach was a lot of cases will shortcut early.

Even though these examples might seem mundane, it’s worth remembering that although JavaScript is generally a simple and clean language, seemingly easy problems can require some attention to detail.


blog comments powered by Disqus