HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Generalized is() type-checking function for JavaScript

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
generalizedjavascriptcheckingfunctiontypefor

Problem

In a complex library I've been working on, I got pretty tired of all of the individual type functions and operators to determine whether I was working with an object or piece of data of a given type. This was especially true when I was checking for inherited prototypes between classes. In an effort to alleviate, I made this generalized is() function.

( function( root ) {
    var is = function( v, t ) {
        if ( typeof v !== 'undefined' ) {
            if ( typeof t === 'string' )
                return typeof v === t;
            else if ( typeof t === 'function' ) {
                if ( typeof v === 'object' )
                    return v instanceof t;
                else if ( typeof v === 'function' )
                    return t.prototype.isPrototypeOf( v.prototype );
                else return false;
            }
        }
        return false;
    };
    root['is'] = is;
}( this ) );


Syntax

  • is(variable, type) where type is any return from typeof



  • returns true if variable typeof === type



  • is(variable, class) where variable is an object and class is a constructor



  • returns true if variable is an instanceof class



  • is(class1, class2) where class is a constructor and class is a constructor



  • returns true if class1's prototype is a descendant of class2's prototype.



Usage

I use this function whenever the type of a value is imperative. One common example is when I need different behaviors depending on the type. As an example:

// typeof myVar === 'number'
if(is(myVar,'number')) {       
    doSomething();
}
//      myVar instanceof Array
elseif (is(myVar,Array)) {     
    doSomethingWithArray();
}
//      typeof myVar === 'object'
elseif (is(myVar,'object')) {  
    doSomethingWithObject();
}


Reasons for this function

The goal is to reduce the amount of typeof, instanceof and isPrototypeOf statements, as well as the need for individualized type checking methods. This certainly seems to accomplish much o

Solution

Code Review

Coding Style

You coding style is quite uncommon. However, it is fine if it is consistent across
your projects.

My personal preference is to use constant ahead of comparison so it looks a
little bit less confusing:

if ('function' === typeof v)


Anyway, in this particular case it is sematically better to use switch so it
emphasises that the variable is immutable within the statement:

switch (typeof t) {
case 'string':
    return t === typeof v;
case 'function':
    ...
}


Some style guides also recommend to remove redundant else after return. This
will decrease indentation and simplify the code statements.

It is better to use a little bit descriptive variable names. For example,
type instead of t and value instead of v.

You can elliminate the variable is by assigning the function directly to
root's property. Or there is a special preference to keep the variable is?

Logic

It is doubtful whether this function should return false for
is(undefined, 'undefined'). It looks like it is a completely valid check that
will fail.

If the argument value is not supported, it may be better to throw an exception
instead of returning plausible value. For example, is(null, null) will return
false, but null is just not supported value of the parameter t.

I understand that it contradicts a little with an original purpose of the function
but it looks like this usage of the function may be quite handy.

Please also be aware of multi-instance environment. If Array object created
within one vm instance (or iframe), instanceof Array will fail. You can find
more examples here: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

Revised Code

(function (root) {
    root.is = function (value, type) {
        if ('undefined' !== typeof value) {
            switch (typeof type) {
            case 'string':
                return type === typeof value;
            case 'function':
                switch (typeof value) {
                case 'object':
                    return value instanceof type;
                case 'function':
                    return type.prototype.isPrototypeOf(value.prototype);
                }
            }
        }
        return false;
    };
}(this));


BTW, its minified version is 8 bytes shorter (with closure-compiler)

Code Snippets

if ('function' === typeof v)
switch (typeof t) {
case 'string':
    return t === typeof v;
case 'function':
    ...
}
(function (root) {
    root.is = function (value, type) {
        if ('undefined' !== typeof value) {
            switch (typeof type) {
            case 'string':
                return type === typeof value;
            case 'function':
                switch (typeof value) {
                case 'object':
                    return value instanceof type;
                case 'function':
                    return type.prototype.isPrototypeOf(value.prototype);
                }
            }
        }
        return false;
    };
}(this));

Context

StackExchange Code Review Q#33956, answer score: 4

Revisions (0)

No revisions yet.