What Type?
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:
- Undefined
- Null
- Boolean
- String
- Number
- 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.
