2

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'};
13
  • 3
    @xcezzz this is a nice approach, but what about typeof {} === typeof [] // true? Commented Jun 6, 2014 at 19:00
  • 2
    @Anatol You just stumbled on why typeof {} === typeof [] -- "I'd expect Object for all objects." They're equal because Arrays are Objects, as are Functions, etc. Only primitives values aren't Objects. The other identified "types" are only given because of special behavior -- e.g. 'function's are callable. Commented Jun 6, 2014 at 19:05
  • 1
    @Anatol But it's not a simple object. An object is created with {} or new Object() Commented Jun 6, 2014 at 19:05
  • 1
    @Derek朕會功夫 Yeah, Strings are Objects, but string values aren't Strings until they're boxed (usually by property accessors). 'foo' instanceof String is false. Commented Jun 6, 2014 at 19:09
  • 4
    @Anatol I'd suggesting using "static" methods on the constructors themselves, following the example of Array.isArray(). These won't interfere or clash with instance properties. Underscorejs includes a collection of such methods that you can use or take as inspiration. Commented Jun 6, 2014 at 19:22

1 Answer 1

3

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"
Sign up to request clarification or add additional context in comments.

3 Comments

I'll gladly take this advice and add this snippet to my standard build, thanks alot! Still, im interested in exactly why it shouldn't be done as in my original question.
Because you're changing the expectations of every piece of code that your code will interact with, and every developer who is going to work on your code after you. If there were a really good reason to do so, I'd say go ahead, but this isn't a really good reason. You're making a problem where there really isn't one. You want to be able to tell the difference between [] and {}, but you're modifying six built-in objects to do so, and inventing your own pseudo type system. Go back to your actual problem, [] vs {}, and choose the simpler solution with the smallest footprint.
@meagar your reasoning is flawless, you identified the underlying fallacy with my idea, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.