Dr. Axel Rauschmayer is a freelance software engineer, blogger and educator, located in Munich, Germany. Axel is a DZone MVB and is not an employee of DZone and has posted 246 posts at DZone. You can read more from them at their website. View Full User Profile

What is JavaScript’s typeof Operator Used for?

01.23.2012
| 3393 views |
  • submit to reddit
JavaScript’s typeof is a complicated beast – it can be used for many things, but also has many quirks. This post lists its use cases, points out problems and presents alternatives.

You should be familiar with the difference between primitives and objects [1].

Checking whether a variable exists and has a value

typeof returns "undefined" in two cases: Either a variable has not been declared or the given value is undefined. Examples:

 > typeof undeclaredVariable === "undefined"
    true

    > var declaredVariable;
    > typeof declaredVariable
    'undefined'

    > typeof undefined
    'undefined'

There are other ways to check whether a value is undefined:

 > var value = undefined;
    > value === undefined
    true

But they throw an exception when used with an undeclared variable – only typeof allows you to do that:

 > undeclaredVariable === undefined
    ReferenceError: undeclaredVariable is not defined

Note: uninitialized variables, missing parameters and non-existent properties are not problematic, because they can all be accessed and have the value undefined:

> var declaredVariable;
    > declaredVariable === undefined
    true

    > (function (x) { return x === undefined }())
    true

    > ({}).foo === undefined
    true

Problem:
typeof is verbose when used for this task.

Better: This is a rare use case, so there might not be a need for a better solution. One could introduce a dedicated operator:

> defined undeclaredVariable
    false
    
    > var declaredVariable;
    > defined declaredVariable
    false

Alternatively, one might also want to just check whether a variable has been declared:

> declared undeclaredVariable
    false
    
    > var declaredVariable;
    > declared declaredVariable
    true


Checking that a value is neither undefined nor null

The following expression checks that x is neither undefined.

typeof x !== undefined && x !== null

Problems:
There is no simple positive check and no negative check for null via typeof, because typeof null is "object" (the most “famous” typeof bug):

 > typeof null
    'object'

Better:
A function for performing this check.

 function isDefined(x) {
        return x !== null && x !== undefined;
    }

Another possibility is to introduce a “default operator” that returns defaultValue if myValue isn’t defined:

    myValue ?? defaultValue

The above expression is equivalent to

   (myValue !== undefined && myValue !== null) ? myValue : defaultValue

Furthermore,

myValue ??= defaultValue

is an abbreviation for

    myValue = myValue ?? defaultValue

Having a similar operator for property access would be useful, too:

    obj.??foo.??bar

The above is equivalent to:

    (obj !== undefined || obj !== null) ?
        (obj.foo !== undefined || obj.foo !== null) ?
            obj.foo.bar
        : obj.foo
    : obj

Checking for definedness will become somewhat less important with default parameter values in ECMAScript.next.

Distinguishing between objects and primitives

The following function checks whether x is an object:

    function isObject(x) {
        return (typeof x === "function"
                || (typeof x === "object" && x !== null));
    }

Problems:
The above check is complicated by the fact that typeof considers functions different from objects and that typeof null is "object".

Better: The above function is a pretty good solution. The following way of detecting an object is also frequently used:

    function isObject2(x) {
        return x === Object(x);
    }

Caveat: You might think that you could use instanceof Object here. But instanceof uses the prototype of an object to determine whether the instance-of relationship holds and you can create an object that doesn’t have a prototype ():

    > var obj = Object.create(null);
    > Object.getPrototypeOf(obj)
    null

obj is indeed an object, but not an instance of anything:

    > typeof obj
    'object'
    > obj instanceof Object
    false

You’ll rarely encounter this kind of object in practice, but it can exist and there are uses for it.

What is the type of a primitive value?

typeof is the best way to determine the type of a primitive value.

    > typeof "abc"
    'string'
    > typeof undefined
    'undefined'

Problem:
You have to be aware of the typeof null quirk.

    > typeof null  // beware!
    'object'

Better:
The following function is a fix (for this use case).

    function getPrimitiveTypeName(x) {
        var typeName = typeof x;
        switch(typeName) {
            case "undefined":
            case "boolean":
            case "number":
            case "string":
                return typeName;
            case "object":
                if (x === null) {
                    return "null";
                }
            default: // fall through from prev. case
                throw new TypeError("Argument isn’t primitive: "+x);
        }
    }

Best:
It would be great to have a function getTypeName() that performs the above algorithm for primitives and returns the value of the internal [[Class]] property for objects. [2] shows how such a function can be implemented.

Is a value a function?

typeof can be used to check whether a value is a function.
    > typeof function () {}
    'function'
    > typeof Object.prototype.toString
    'function'
In principle, instanceof Function is another way of performing this check. At first glance, it is more elegant. But browsers exhibit a strange quirk: Each frame and window has its own global variables. Hence, if you pass an object from one frame to another, instanceof ceases to work, because the right-hand side refers to a different constructor. That is why ECMAScript 5 has Array.isArray(). It would be nice to have a cross-frame mechanism for checking whether an object is an instance of a given constructor. The aforementioned getTypeName() is one possible work-around, but there might be a more fundamental (as in: cleaner) solution.

Summary

The following would be the most valuable additions to JavaScript, taking on some of typeof’s current responsibilities:

  • isDefined() (e.g. as Object.isDefined()): either as a function or as one or more operators (#2)
  • isObject() (#3)
  • getTypeName() (#4)
  • A cross-frame mechanism for checking whether an object is an instance of a given constructor (#5)
Use case #1, checking whether a variable has been declared, is probably not important enough to warrant its own operator.

References

  1. JavaScript values: not everything is an object
  2. Improving the JavaScript typeof operator
Published at DZone with permission of Axel Rauschmayer, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)