You want a Role, not a Type.

Well defined role. Not a type.
Well defined role. Not a type.

[Originaly published 2009 Nov.]

Few days ago one jQuery discussion, “blossomed” around good old: isObject() or is it isArray() , dilemma. One of few never ending javascript dramas.

Yet another typeof related discussion? That was my initial reaction. A very stubborn little issue, especially considering that javascript is typeless language. Which in reality is a misnomer? It is impossible to have true and pure “no types involved” language.

Rather there is a type system behind which gives the illusion, that types do not exist. It transparently coerces values from ‘type’ A to ‘type’ B. This is usually implemented with the help of a “root type”. An object that encapsulates type issues. Sometimes this is called: meta type. Type of types.

For example in VBScript we have VARIANT. In JavaScript, there is a slight confusion, unfortunately. JavaScript implementations have something one might call: “root type”. It is implemented and called: “Object”. But. ECMA 5 spec is not mirroring this, explicitly. So in JavaScript, we have automatic type coercion rules. But they are not specified in simple object oriented terms. That is: global JavaScript object, called “Object” is not specified as a meta type. For example, intinsic number type is not specified as a “kind-of-a” Object, that is an object that inherits from “Object”.

And then, there is the unfortunate typeof operator. And its even more unfortunate
Instead of indulging in a lengthy explanation on why are they both problematic, I will show this code:

var A = [1,2,3] ;
A instanceof Array
/*returns: true*/
typeof Array
/*returns: function*/

Well, there is no any other so (seemingly) simple language like JavaScript, which can confuse a good natured beginer, so much. Here she is bound to ask you: How can A be an “intanceof” Array, if typeof Array is clearly a “function” ? Well, in JavaScript it certainly is not, but then it certainly appears to be. Ugh, imagine explaining this to someone who knows nothing of, object orientation, C++, or C# or Java and who is learning programming through JavaScript. Or this little ‘number’:
var color1 = new String("green");
color1 instanceof String;
// returns true
var color2 = "coral";
color2 instanceof String;
// returns false
// (color2 is not a String object, it is a string literal)

Ok, these are the problems, we need some solutions. Let me jump stright back to the point. Beginners or not, JavaScript developers have simply given up on those two above. Each and every javascript library has somewhere inside at least two methods, which are answering a simple (?) question : is this thing an Array or is this thing an Object ?

This is the barre minimum, since typeof returns “object” for both Objects and Arrays. Is this supposed to be or not, is a moot point, which can be properly answered only if we think of the implementation of the language. Then we will realise that typeof sometimes “reveals” the parent object and sometimes not.

typeof {}
// returns: "object"
typeof []
// returns: "object"
typeof ""
// returns: "string", because "" is a string literal
typeof new String()
// returns "object"
typeof 1
// returns: "number", 1 is intrinsic type
typeof new Number(1)
// returns "object"


Most importantly type of array is returned as the type of its (real) prototype: “object”. Why is this and how is this is discussed countless of times elsewhere. What we need is solution for a robust and feasible way to encapsulate this issues and “forget” about this. This is done usually in the form of two simple (or not, it depends) on functions :

"use strict";

(function (glob) {

var TOS =  Object.prototype.toString ;
glob.isFunction = function(obj) {
  return ( === "[object Function]");

glob.isArray = function(obj) {
return ( === "[object Array]");


Nice and simple and works. Well, almost. In IE7 and before, this isFunction, will not work.

// alert() is a function, yes ?
/* returns : false in IE < 8 */

Object.prototype.ToString(obj) , has “special” behavior if given an argument. It returns a full ECMA 5 “Class” name. An “type descriptor”, of the argument given. In IE, isFunction() has a problem. isArray() has no such problems. It works. For the time being. What do I mean by this? I mean that I do not like this implementation. This implementation depends on well behaved browsers. This means, that we expect each and every browser to return these exact strings . In the present and future. Including some new and peculiar little browser on some new mobile future platform? Hm, I would not bet on this. Some will, but I would not.

Towards the Solution

I do happen to think that first of all conceptually it has to be clear that “type” is overloaded term here. It seems we will be able to decouple ourselves from javascript type issues. First of all (as ever) we have to sort out the terminology.( conceptology ?) returns what I shall call: “type descriptor”
Type descriptor format is well known ES5 concept. Bellow is a formal definition of few strings which are reserved in ES5. Just like “use strict” is a reserved string. I will formalise this as :

<type descriptor> := "[ object " + <role> + "]"
<role> := "Argument" | "Object" | "Array" | "Error"
| "RegExp" | "Number" | "String" | "Math"
| "Function" | "JSON"


(Yes, “Argument” and “JSON” are part of ES5.) Type descriptor is a string naming the type and the role of the object in JavaScript. And the key word we have here is: the role!
We use this to differentiate an ES5 entity typeof name from its Role.
The core idea is to use the Role concept to differentiate between the type and the role.

Array related example: [] is an “object” whose role is to be an “Array”.

Therefore JavaScript “typeof” operator returns the “type name”, NOT the “role name”. And there is indeed no “roleof” operator in JavaScript. There is no operator in JavaScript, which would simply return a proper role name on an array. There is only one already mentioned  thing: Object.prototype.toString() :

//[]) === "[object Array]";
// returns true
// full descriptor text would be
// [] object type is : "object"
// [] object role is : "Array"
// type + role = description

description = type + role

Recap time. Type alone is not enough as a full description about ES5 entities. 99% of times what are we actually interested in are roles, not types of JavaScript objects. We want to know (for example) if something is an Array or Date or RegEx. In 99% of cases we do not want to know that they are all objects. We know that already. To clarify all if this, let me present to You, a small framework based on this discussion.

$Revision: 5 $
$Date: 8/11/09 16:46 $
Copyright (c) 2009-2017 by DBJ.ORG
Appache 2 Licence
(function() {
dbj || (dbj = {});
var globals = [
new Array, new Boolean, new Date, new Error,
new Function, Math,
new Number, new Object,
new RegExp, new String
if ("object" === typeof Arguments) // ECMA5 Arguments object
globals[globals.length] = Arguments;

if ("object" === typeof JSON) // add JSON if exist as inbuilt object
globals[globals.length] = JSON;

dbj.role = {
name: function(o) {
/// NOTE: for IE < 8, some DOM objects function bellow will return "object"
/// for methods. example: window.alert returns "object"
names: {
/// holds distinctive role names, and their unique role id's
/// { "Array" : 0, ... }
/// generate dbj.role.names object,
/// with distinctive role names
/// and their type ID's
var name_ = "";
for (var j = 0; j < globals.length; j++) {
name_ =[j]);
dbj.role.names[name_] = j;

/// generate<role name>() checks
/// we compare role id's bellow, not names
/// so we compare numbers, not strings
for (var j in dbj.role.names) {
dbj.role["is" + j] = Function(
"return dbj.role.names[] === dbj.role.names['" + j + "'];");

What we have generated here, is first of all one “repository” of roles and their id’s.

Array: 0, Boolean: 1, Date: 2, Error: 3,
Function: 4, Math: 5,
Number: 6, Object: 7, RegExp: 8,
String: 9, JSON: 10

Then, we have generated “is” function for each role defined. For example, for Function we have generated:

dbj.role.isFunction = function (o) {
return dbj.role.names[]
// dbj.role.names['Function'];


Please nothe that here we actually compare not the string name, but the ID of the role “Function”, which above is : 4, with the ID of the computed role of the argument “o”.

Ok, but really: Why ‘Role’, why not ‘Class’ ?

Simply because Class is one very overloaded term. Especially if one deals with several languages in the same time. ES5 is using the term ‘Class’, for one of its ‘internal property’-es. The “ES5 spec” says:

The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of “Arguments”, “Array”, “Boolean”, “Date”, “Error”, “Function”, “JSON”, “Math”, “Number”, “Object”, “RegExp”, and “String”. The value of a [[Class]] internal property is used internally to distinguish different kinds of built-in objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString()

Hooray ! This is excellent news! String values : “Arguments”, “Array”, “Boolean”, “Date”, “Error”, “Function”, “JSON”, “Math”, “Number”, “Object”, “RegExp”, and “String”, are reserved words by the latest ES5 spec. This is what we use as role names, and this is what comes out of Object.prototype.toString().

But… I beg to differ on using the term “Class”, in this context. Simply because “class” as used here is not what “class” means elsewhere in OOD, OOA, C++, C# or Java. There is no prescribed standard “class hierarchy” behind an JavaScript implementation. There are no classes in JavaScript. Just objects and prototypes. Also, the “Class”, is just used (borrowed) and not defined in ECMA Script 5 spec. Instead I have chosen the term “role”, which I think, is much closely related to the reality of the JavaScript nature. So, what is ECMA 5 internal property “Class” is what we call here: the “Role”. And the reserved values of it, is what we use as role names. I do not invent anything here, beside a new term: “Role”.

What about IE ?

I hope I have presented here an simple and useful mechanism, that does its job well. Especially if ubiquitously used, across all the browsers, projects and teams. This mechanism, also seems robust and future proof. From now on I will use this each and every time I need objects Role related information in my JavaScript code. Which is almost always. Also here we are facing IE browser differences, head on. Because of the simple reason: in IE < 8, methods on DOM nodes are treated as objects. Are they “treated” or “implemented” or “thought of” , does not matter. What matter is that in IE 7 or before, we have this situation :

"object" === typeof alert ;
// true in IE < 8
dbj.role.isFunction( alert ) ;
// false in IE < 8

Ok, ok. I am an professional. I will serve my customers. I will not try to educate them instead ;) Solutions for IE < 8, are certainly doable, and perhaps not very elegant. For that please see my next post.


Update 2012 Oct 08

Fortunately since IE8, ES5 in IE behaves better.

"object" === typeof alert ; // FALSE in IE > 7

Therefore I am able to use this very simple (and global) roleof implementation.

// this code is inside my "dbj" namespace
// toString shortcut defined elsewhere
var TOS = Object.prototype.toString ;
top.roleof = function(o) {
/// NOTE: for DOM objects function bellow will return "object"
/// in IE. example: window.alert returns "object"
return o === undefined ? "undefined" : o === null ? "null" :\w+/g)[1];

Now I have an global:


which helps me escape the


pitfalls and debates. And


“suite” is still in there for any case and for Your own comfort:

// works in all browsers excluding IE < 8
dbj.role.isFunction(alert) /* returns: true */
roleof( alert ) /* returns: 'Function' */