简体   繁体   English

变量 === 未定义与 typeof 变量 === “未定义”

[英]variable === undefined vs. typeof variable === "undefined"

The jQuery Core Style Guidelines suggest two different ways to check whether a variable is defined. jQuery Core Style Guidelines提出了两种不同的方法来检查是否定义了变量。

  • Global Variables: typeof variable === "undefined"全局变量: typeof variable === "undefined"
  • Local Variables: variable === undefined局部变量: variable === undefined
  • Properties: object.prop === undefined属性: object.prop === undefined

Why does jQuery use one approach for global variables and another for locals and properties?为什么 jQuery 对全局变量使用一种方法而对局部变量和属性使用另一种方法?

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" .对于未声明的变量, typeof foo将返回字符串文字"undefined" ,而身份检查foo === undefined将触发错误"foo is not defined"

For local variables (which you know are declared somewhere), no such error would occur, hence the identity check.对于局部变量(您知道在某处声明),不会发生此类错误,因此需要进行身份检查。

I'd stick to using typeof foo === "undefined" everywhere.我会坚持在任何地方使用typeof foo === "undefined" 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.我想 jQuery 推荐这两种不同方法的原因是它们在 jQuery 代码所在的函数中定义了自己的undefined变量,因此在该函数中undefined可以防止外部篡改。 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.我还想象某个地方有人对两种不同的方法进行了基准测试,发现foo === undefined更快,因此决定这是要走的路。 [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. [更新:如评论中所述,与undefined的比较也略短,这可能是一个考虑因素。]然而,实际情况中的收益将完全微不足道:此检查永远不会成为任何类型的瓶颈,并且你失去的东西很重要:评估主机对象的属性进行比较可能会引发错误,而typeof检查永远不会。

For example, the following is used in IE for parsing XML:例如,在 IE 中使用以下内容来解析 XML:

var x = new ActiveXObject("Microsoft.XMLDOM");

To check whether it has a loadXML method safely:要安全地检查它是否具有loadXML方法:

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 .我忘记提及的typeof检查的另一个优点是它也适用于未声明的变量,而foo === undefined检查则不然,实际上会抛出一个ReferenceError Thanks to @LinusKleen for reminding me.感谢@LinusKleen 提醒我。 For example:例如:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

Bottom line: always use the typeof check.底线:始终使用typeof检查。

Yet another reason for using the typeof-variant: undefined can be redefined.使用 typeof-variant 的另一个原因: undefined可以重新定义。

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

The result of typeof variable cannot. typeof variable的结果不能。

Update : note that this is not the case in ES5 there the global undefined is a non-configurable, non-writable property:更新:请注意,在 ES5 中情况并非如此,全局undefined是一个不可配置、不可写的属性:

15.1.1 Value Properties of the Global Object 15.1.1 全局对象的值属性
[...] [...]
15.1.1.3 undefined 15.1.1.3 未定义
The value of undefined is undefined (see 8.1). undefined值为 undefined(见 8.1)。 This property has the attributes该属性具有以下属性
{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

But it still can be shadowed by a local variable:但它仍然可以被局部变量遮蔽:

(function() {
  var undefined = "foo";
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})()

or parameter:或参数:

(function(undefined) {
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})("foo")

Because undefined is not always declared, but jQuery declares undefined in its main function.因为undefined并不总是被声明的,但是 jQuery 在它的 main 函数中声明了undefined So they use the safe undefined value internally, but outside, they use the typeof style to be safe.所以他们在内部使用安全的undefined值,但在外部,他们使用typeof样式是安全的。

Who is interested in the performance gain of variable === undefined , may take a look here, but it seems to be a chrome optimization only.谁对variable === undefined的性能增益感兴趣,可以看看这里,但它似乎只是一个 chrome 优化。

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.对于局部变量,使用localVar === undefined检查会起作用,因为它们必须在局部作用域内的某处定义,否则它们将不被视为局部变量。

For variables which are not local and not defined anywhere, the check someVar === undefined will throw exception: Uncaught ReferenceError: j is not defined对于非本地且未在任何地方定义的变量,检查someVar === undefined将抛出异常: 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.当您像这样进行检查时: typeof x === 'undefined' ,您实际上是在问这个问题:请检查变量x存在(已定义)源代码中的某处。 (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.如果您了解 C# 或 Java,则永远不会进行此类检查,因为如果它不存在,则不会编译。

<== Fiddle Me ==> <== 摆弄我 ==>

Summary:概括:

When at global scope we actually want to return true if the variable is not declared or has the value undefined :在全局范围内,如果变量未声明或值为undefined我们实际上希望返回 true :

 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.因为在全局范围内,我们不能 100% 确定是否声明了一个变量,这可能会给我们一个引用错误。 When we use the typeof operator on the unknown variable we are not getting this issue when the variable is not declared:当我们在未知变量上使用typeof运算符时,我们不会在未声明变量时遇到此问题:

 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.这是因为typeof运算符在未声明变量或当前保存的值undefined时返回undefined字符串,这正是我们想要的。


  • 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对于对象属性,我们没有这个问题,因为当我们尝试查找一个不存在的对象属性时,我们也会得到值undefined

 var obj = {}; console.log(obj.myProp === undefined);

typeof a === 'undefined'更快然后a === 'undefined'由节点v6.9.1约2倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM