Typeof in JavaScript is actually very complex. It can be used to do many things, but it also has many weird manifestations. This article lists its multiple uses and points out existing problems and solutions.
/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof
> typeof undefined
'undefined'
> typeof null // well-known bug
'object'
> typeof true
'boolean'
> typeof 123
'number'
> typeof "abc"
'string'
> typeof function() {}
'function'
> typeof {}
'object'
> typeof []
'object'
> typeof unknownVariable
'undefined'
1. Check whether a variable exists and has a value.
Typeof will return "undefined" in two cases: when a variable is not declared, and when the value of a variable is undefined. For example:
> typeof undeclaredVariable === "undefined" true > var declaredVariable; > typeof declaredVariable 'undefined' > typeof undefined 'undefined'
There are other ways to detect whether a value is undefined:
> var value = undefined; > value === undefined true
However, if this method is used on an undeclared variable, an exception will be thrown, because only typeof can detect undeclared variables normally without reporting an error:
> undeclaredVariable === undefined ReferenceError: undeclaredVariable is not defined
Note: Uninitialized variables, formal parameters that are not passed in parameters, and non-existent properties will not have the above problems, because they are always accessible and the values are always undefined:
> var declaredVariable; > declaredVariable === undefined true > (function (x) { return x === undefined }()) true > ({}).foo === undefined true
Translator's note: Therefore, if you want to detect whether a global variable that may not be declared exists, you can also use if(){}
Question: Typeof seems complicated when completing such tasks.
Solution: This kind of operation is not very common, so some people think there is no need to find a better solution. However, someone may propose a special operator:
> defined undeclaredVariable false > var declaredVariable; > defined declaredVariable false
Or maybe someone needs an operator that detects whether a variable is declared:
> declared undeclaredVariable false > var declaredVariable; > declared declaredVariable true
Translator's note: In perl, the defined operator above is equivalent to defined(), and the declared operator above is equivalent to exists(),
2. Determine that a value is not equal to undefined and not equal to null
Question: If you want to detect whether a value has been defined (the value is not undefined or null), then you have encountered a weird manifestation of typeof (that is considered a bug): typeof null returns "object":
> typeof null 'object'
Translator's note: This can only be said to be a bug in the original JavaScript implementation, and now the standard is standardized. V8 once corrected and implemented typeof null === "null", but it finally proved unfeasible./?id=harmony:typeof_null
Solution: Do not use typeof to do this task, use the following function instead:
function isDefined(x) { return x !== null && x !== undefined; }
Another possibility is to introduce a "default value operator". If myValue is not defined, the following expression will return defaultValue:
myValue ?? defaultValue
The above expression is equivalent to:
(myValue !== undefined && myValue !== null) ? myValue : defaultValue
Or:
myValue ??= defaultValue
In fact, it is a simplification of the following statement:
myValue = myValue ?? defaultValue
When you access a nested property, such as bar, you may need the help of this operator:
If obj or is undefined, the above expression will throw an exception. An operator.?? Can the above expression return the first attribute encountered with undefined or null value when it traverses the properties of one layer by one:
obj.??foo.??bar
The above expression is equivalent to:
(obj === undefined || obj === null) ? obj : ( === undefined || === null) ? :
3. Distinguish between object values and original values
The following function is used to detect whether x is an object value:
function isObject(x) { return (typeof x === "function" || (typeof x === "object" && x !== null)); }
Problem: The above detection is more complicated because typeof treats functions and objects as different types, and typeof null returns "object".
Solution: The following methods are also often used to detect object values:
function isObject2(x) { return x === Object(x); }
Warning: You may think that you can use instanceof Object to detect here, but instanceof determines the instance relationship by using a prototype using an object. So what should I do if an object without a prototype:
> var obj = (null); > (obj) null
obj is indeed an object, but it is not an instance of any value:
> typeof obj 'object' > obj instanceof Object false
In practice, you may rarely encounter such an object, but it does exist and has its purpose.
Translator's note: It is an object that exists by default and has no prototype.
>()null>typeof 'object'> instanceof Object false
4. What is the type of the original value?
typeof is the best way to view a type of a certain original value.
> typeof "abc" 'string' > typeof undefined 'undefined'
Question: You must know the weird behavior of typeof null.
> typeof null // Be careful! 'object'
Solution: The following function can fix this problem (for this use case only).
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: // The previous judgment failed throw new TypeError("The parameter is not a primitive value: "+x); } }
A better solution: Implement a function getTypeName(), in addition to returning the type of the original value, it can also return the internal [[Class]] attribute of the object value. Here we talk about how to implement this function (Translator's note: $.type in jQuery is the implementation like this)
5. Whether a value is a function
typeof can be used to detect whether a value is a function.> typeof function () {} 'function' > typeof 'function'
In principle, instanceof Function can also perform this kind of requirement detection. At first glance, it seems that the writing is more elegant. However, the browser has a quirk: each framework and window has its own global variable. Therefore, if you pass an object in a certain framework into another framework, instanceof does not work properly because the two frameworks have different constructors. This is why there is a() method in ECMAScript5. It would be nice if there is a method that crosses the framework to check if an object is an instance of a given constructor. The above getTypeName() is a workaround, but maybe there is a more fundamental solution.
6. Overview
The following mentioned should be the most urgent need in JavaScript at present, and it can replace some functional features of the current responsibilities of typeof:
isDefined() (such as()): can be used as a function or an operator
isObject()
getTypeName()
A mechanism that can detect whether an object is an instance of a specified constructor across frameworks
To check whether a variable has been declared for such a requirement, it may not be necessary to have its own operator.