可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
The jQuery Core Style Guidelines suggest two different ways to check whether a variable is defined.
- Global Variables:
typeof variable === \"undefined\"
- Local Variables:
variable === undefined
- Properties:
object.prop === undefined
Why does jQuery use one approach for global variables and another for locals and properties?
回答1:
For undeclared variables, typeof foo
will return the string literal \"undefined\"
, whereas the identity check foo === undefined
would trigger the error \"foo is not defined\".
For local variables (which you know are declared somewhere), no such error would occur, hence the identity check.
回答2:
I\'d stick to using typeof foo === \"undefined\"
everywhere. That can never go wrong.
I imagine the reason why jQuery recommends the two different methods is that they define their own undefined
variable within the function that jQuery code lives in, so within that function undefined
is safe from tampering from outside. I would also imagine that someone somewhere has benchmarked the two different approaches and discovered that foo === undefined
is faster and therefore decided it\'s the way to go. [UPDATE: as noted in the comments, the comparison with undefined
is also slightly shorter, which could be a consideration.] However, the gain in practical situations will be utterly insignificant: this check will never, ever be any kind of bottleneck, and what you lose is significant: evaluating a property of a host object for comparison can throw an error whereas a typeof
check never will.
For example, the following is used in IE for parsing XML:
var x = new ActiveXObject(\"Microsoft.XMLDOM\");
To check whether it has a loadXML
method safely:
typeof x.loadXML === \"undefined\"; // Returns false
On the other hand:
x.loadXML === undefined; // Throws an error
UPDATE
Another advantage of the typeof
check that I forgot to mention was that it also works with undeclared variables, which the foo === undefined
check does not, and in fact throws a ReferenceError
. Thanks to @LinusKleen for reminding me. For example:
typeof someUndeclaredVariable; // \"undefined\"
someUndeclaredVariable === undefined; // throws a ReferenceError
Bottom line: always use the typeof
check.
回答3:
Yet another reason for using the typeof-variant: undefined
can be redefined.
undefined = \"foo\";
var variable = \"foo\";
if (variable === undefined)
console.log(\"eh, what?!\");
The result of typeof variable
cannot.
Update: note that this is not the case in ES5.
回答4:
Who is interested in the performance gain of variable === undefined
, may take a look here, but it seems to be a chrome optimization only.
- http://jsperf.com/type-of-undefined-vs-undefined/30
- http://jsperf.com/type-of-undefined-vs-undefined
回答5:
Because undefined
is not always declared, but jQuery declares undefined
in its main function. So they use the safe undefined
value internally, but outside, they use the typeof
style to be safe.
回答6:
For local variables, checking with localVar === undefined
will work because they must have been defined somewhere within the local scope or they will not be considered local.
For variables which are not local and not defined anywhere, the check someVar === undefined
will throw exception: Uncaught ReferenceError: j is not defined
Here is some code which will clarify what I am saying above. Please pay attention to inline comments for further clarity.
function f (x) {
if (x === undefined) console.log(\'x is undefined [x === undefined].\');
else console.log(\'x is not undefined [x === undefined.]\');
if (typeof(x) === \'undefined\') console.log(\'x is undefined [typeof(x) === \\\'undefined\\\'].\');
else console.log(\'x is not undefined [typeof(x) === \\\'undefined\\\'].\');
// This will throw exception because what the hell is j? It is nowhere to be found.
try
{
if (j === undefined) console.log(\'j is undefined [j === undefined].\');
else console.log(\'j is not undefined [j === undefined].\');
}
catch(e){console.log(\'Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.\');}
// However this will not throw exception
if (typeof j === \'undefined\') console.log(\'j is undefined (typeof(x) === \\\'undefined\\\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.\');
else console.log(\'j is not undefined [typeof(x) === \\\'undefined\\\'].\');
};
If we call the above code like this:
f();
The output would be this:
x is undefined [x === undefined].
x is undefined [typeof(x) === \'undefined\'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
If we call the above code like these (with any value actually):
f(null);
f(1);
The output will be:
x is not undefined [x === undefined].
x is not undefined [typeof(x) === \'undefined\'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
When you do the check like this: typeof x === \'undefined\'
, you are essentially asking this: Please check if the variable x
exists (has been defined) somewhere in the source code. (more or less). If you know C# or Java, this type of check is never done because if it does not exist, it will not compile.
<== Fiddle Me ==>
回答7:
Summary:
When at global scope we actually want to return true if the variable is not declared or has the value undefined
:
var globalVar1;
// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);
// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);
Because in global scope we are not 100% sure if a variable is declared this might give us a referenceError. When we use the typeof
operator on the unknown variable we are not getting this issue when the variable is not declared:
var globalVar1;
console.log(typeof globalVar1 === \'undefined\');
console.log(typeof globalVar2 === \'undefined\');
This is due to the fact that the typeof
operator returns the string undefined
when a variable is not declared or currently hold the value undefined
which is exactly what we want.
- With local variables we don\'t have this problem because we know beforehand that this variable will exist. We can simply look in the respective function if the variable is present.
- With object properties we don\'t have this problem because when we try to lookup an object property which does not exist we also get the value
undefined
var obj = {};
console.log(obj.myProp === undefined);
回答8:
typeof a === \'undefined\'
is faster then a === \'undefined\'
by about 2 times on node v6.9.1.