What is JavaScript’s typeof Operator Used for?
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.
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:
There are other ways to check whether a value is undefined:
But they throw an exception when used with an undeclared variable – only typeof allows you to do that:
Note: uninitialized variables, missing parameters and non-existent properties are not problematic, because they can all be accessed and have the value undefined:
Problem: typeof is verbose when used for this task.
Alternatively, one might also want to just check whether a variable has been declared:
The following expression checks that x is neither undefined.
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):
Better: A function for performing this check.
Another possibility is to introduce a “default operator” that returns defaultValue if myValue isn’t defined:
The above expression is equivalent to
Furthermore,
is an abbreviation for
Having a similar operator for property access would be useful, too:
The above is equivalent to:
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:
Problems: The above check is complicated by the fact that typeof considers functions different from objects and that typeof null is "object".
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 ():
obj is indeed an object, but not an instance of anything:
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.
Problem: You have to be aware of the typeof null quirk.
Better: The following function is a fix (for this use case).
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.
Summary
The following would be the most valuable additions to JavaScript, taking on some of typeof’s current responsibilities:
References
Published at DZone with permission of Axel Rauschmayer, author and DZone MVB.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)
References
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
Tags:





