Question

Because of the need constantly arising on detecting data types, and I have written the following function that so far has served well, so I would like to share the code with you. However I'm beginning to think that this maybe isn't an efficient way for type detection. How could I enhance this function? Or am I making a mistake, and shouldn't even do this?

Based on cade's answer I reviewed and edited the code:

function detectType(data) {
    // analyze data to distinguish object types from primitive types
    var dataType = typeof data;
    var toClass = {}.toString; // this is used to detect object types
    var isPrimitive;
    var isFalsy = false;
    switch(dataType) {
        case 'string':
            isFalsy = !data;
            if(isFalsy) {
                dataType = 'empty string'; // Only if you want to distingush empty strings
            }
            isPrimitive = true;
            break;
        case 'number':
            isFalsy = !data;
            if(isFalsy) {
                if(isNaN(data))
                    dataType = 'NaN';   // it is strange that JavaScript considers NaN a number
                else {
                    dataType = '0';     // only needed if you want to distinguish zeros
                    if(1/data < 1/0)
                        dataType = '-0';
                }
            } else if(!isFinite(data)) {    // Although infinity is considered a number you might want to distinguish it
                dataType = 'infinity';
                if(data < Infinity)
                    dataType = '-infinity';
            }
            isPrimitive = true;
            break;
        case 'boolean':
            isFalsy = !data;
            isPrimitive = true;
            break;
        case 'object':
            isFalsy = !data;
            dataType = toClass.call(data).slice(8, -1).toLowerCase();
            switch(dataType) {
                case 'string':
                    dataType = 'object string';
                    break;
                case 'number':
                    dataType = 'object number';
                    break;
                case 'boolean':
                    dataType = 'object boolean';
                    break;
            }
            isPrimitive = false;
            break;
        case 'function':
            isFalsy = !data;
            isPrimitive = false;
            break;
        case 'undefined':
            isFalsy = !data;
            isPrimitive = false;
            break;
        }
    return [dataType, isPrimitive ,isFalsy];
}

I tried a few things in console and got these results:

detectType(-0)
["-0", true, true]
detectType(9)
["number", true, false]
detectType(new Number(3))
["object number", false, false]
detectType('')
["empty string", true, true]
detectType('foo')
["string", true, false]
detectType(new String('bar'))
["object string", false, false]
detectType(true)
["boolean", true, false]
detectType(new Boolean(false))
["object boolean", false, false]
detectType(document.body)
["htmlbodyelement", false, false]
detectType(-0)
["-0", true, true]
detectType(-Infinity)
["-infinity", true, false]
detectType(/a-zA-Z/)
["regexp", false, false]

Now It can even detect html elements too, it is possible to check for -0, +0 and -Infinity, +Infinity, although these are considered numbers, one might find it useful to distinguish too large or too small numbers such is infinity or -0.

Was it helpful?

Solution

Much of your switch/case control statement can be removed and replaced w/ something like this:

  toClass.call(obj).slice(8, -1);

to obtain the type. This will remove the excess fluff and return

Number, Function, etc, ...

Also, typeof does not work for null and arrays, as they are reported as objects.

Your falsy logic can be simplified to:

!data

I like how you use typeof and toString to differentiate between

3

and

new Number(3)

even though the second form would not be best-practice.

OTHER TIPS

If you want to improve the functionality of the function you are currently using, I would check out the underscore.js annotated code. Underscore is a utility library for javascript and includes a lot of helpful functions. They have at least 15 different 'is[Type]' functions (ex. isString, isArray).

If you scroll down the annotated code and check out those functions, I'm sure you will be able to find some helpful comments.

If you decide not to continue working on this, underscore is a great option for a typeof enhancement.

Good Luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top