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 several uses and points out existing problems and solutions.
The premise of reading this article is that you should now know the difference between the original value and the object value.
Check whether a variable exists and has a value
typeof will return "undefined" in two cases:
1. Variables are not declared
2. The value of the 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(){} can also be used if(){} if you want to detect whether a global variable that may not be declared exists.
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. But maybe someone would 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().
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 the current standard is standardized in this way. V8 has fixed and implemented typeof null === "null", but it turned out to be unfeasible. /?id=harmony:typeof_null.
(Translator's note: typeof returns "object" when operating null, which is a bug in the JavaScript language itself. Unfortunately, this bug can never be fixed because too much existing code has relied on such behavior. But is null an object? * has a discussion on this issue: /questions/801032/null-object-in-javascript/7968470#7968470@justjavac)
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", in which the following expression returns defaultValue if myValue is not defined:
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 allow the above expression to return the first encountered attribute with undefined or null value when it traverses the properties one layer by one:
obj.??foo.??bar
The above expression is equivalent to:
(obj === undefined || obj === null) ? obj
: ( === undefined || === null) ?
:
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 instanceof Object can be used to detect, but instanceof is used to judge 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 the only built-in object without prototypes.
>()
null
>typeof
'object'
> instanceof Object
false
What is the type of the original value?
typeof is the best way to view the type of a certain original value.
> typeof "abc"
'string'
> typeof undefined
'undefined'
Question: You have to 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: // No previous judgments have been passed
throw new TypeError("The parameter is not a primitive value: "+x);
}
}
A better solution: Implement a function getTypeName(), which can return the type of the original value, and can also return the internal [[Class]] property of the object value. Here we talk about how to implement this function (Translator's note: $.type in jQuery is this implementation)
Is a value 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 detection of such requirements. At first glance, it seems that the writing style is more elegant. However, browsers have a quirk: each frame and window has its own global variables. Therefore, if you pass objects in one framework into another, 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 cross-frame method that checks whether an object is an instance of a given constructor. The above getTypeName() is a workaround available, but maybe there is a more fundamental solution.
Summary
The following mentioned should be the most urgent need in JavaScript at present, and it can replace some functional features of typeof's current responsibilities:
•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.