Anatol
Anatol

Reputation: 191

Is this a valid way to determine JavaScript variable types?

Any developer writing JS sooner or later encounters this, rather infuriating behaviour:

typeof []; // 'object'

While there are workarounds such as instanceof and accessing a variable's .constructor property, this just came to my mind:

Array.prototype.TYPE = 'Array';
String.prototype.TYPE = 'String';
Boolean.prototype.TYPE = 'Boolean';
Object.prototype.TYPE = 'Object';
RegExp.prototype.TYPE = 'RegExp';
Number.prototype.TYPE = 'Number';

// and therefore:
[1,2,'bar', {baz: 'foo'}].TYPE === 'Array'; // true
"But life itself, my wife, and all the world / Are not with me esteemed above thy life".TYPE // 'String'
(42).TYPE === 'Number'; // true
// and so on

I know it is generally frowned upon to modify native prototypes, That said, is there any other issue with this "pattern"?

UPDATE: Some comments offer alternative solutions like usage of Object.prototype.toString and more. These are certainly all valid approaches that have their use cases. But still, what I'm primarily interestest in, is whether there might be some case in which adding a property to native constructor prototypes would actually cause a problem :)

UPDATE:

A safer way?

Array.prototype.getType = function() {return 'Array'};
String.prototype.getType = function() {return 'String'};
Boolean.prototype.getType = function() {return 'Boolean'};
Object.prototype.getType = function() {return 'Object'};
RegExp.prototype.getType = function() {return 'RegExp'};
Number.prototype.getType = function() {return 'Number'};

Upvotes: 2

Views: 108

Answers (1)

user229044
user229044

Reputation: 239581

Douglas Crockford recommends writing your own typeOf function for exactly this reason:

... The new typeOf global function is intended to replace the defective typeof operator. It produces the same result as typeof, except that it returns 'null' for null and 'array' for arrays.

He implements it thusly:

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (typeof value.length === 'number' &&
                    !(value.propertyIsEnumerable('length')) &&
                    typeof value.splice === 'function') {              
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

typeOf({}) //=> "object"

typeOf([]) //=> "array"

Upvotes: 3

Related Questions