jQuery核心风格指南提供了两种不同的方法来检查变量是否被定义。

全局变量:typeof variable === "undefined" 局部变量:variable === undefined 属性:对象。Prop === undefined

为什么jQuery对全局变量使用一种方法,而对局部变量和属性使用另一种方法?


当前回答

对于局部变量,使用localVar === undefined进行检查是有效的,因为它们必须在局部作用域内的某个地方定义,否则它们将不被视为局部变量。

对于非本地且未在任何地方定义的变量,someVar === undefined检查将抛出异常:Uncaught ReferenceError: j未定义

下面是一些代码,可以澄清我上面所说的内容。为了更清晰,请注意内联注释。

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\'].');
};

如果我们像这样调用上面的代码:

f();

输出是这样的:

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.

如果我们像这样调用上面的代码(实际上是任意值):

f(null); 
f(1);

输出将是:

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.

当你像这样做检查:typeof x === 'undefined',你本质上是在问:请检查变量x是否存在(已定义)在源代码的某个地方。(多多少少)。如果你知道c#或Java,这种类型的检查永远不会进行,因为如果它不存在,它就不会编译。

<==小提琴我==>

其他回答

我将坚持在任何地方使用typeof foo === "undefined"。这永远不会出错。

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.

以IE中解析XML为例:

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

检查是否有loadXML方法:

typeof x.loadXML === "undefined"; // Returns false

另一方面:

x.loadXML === undefined; // Throws an error

更新

typeof检查的另一个优点是,我忘了提到它也适用于未声明的变量,而foo === undefined检查不能,实际上会抛出一个ReferenceError。谢谢@LinusKleen的提醒。例如:

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

底线:总是使用typeof检查。

对于局部变量,使用localVar === undefined进行检查是有效的,因为它们必须在局部作用域内的某个地方定义,否则它们将不被视为局部变量。

对于非本地且未在任何地方定义的变量,someVar === undefined检查将抛出异常:Uncaught ReferenceError: j未定义

下面是一些代码,可以澄清我上面所说的内容。为了更清晰,请注意内联注释。

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\'].');
};

如果我们像这样调用上面的代码:

f();

输出是这样的:

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.

如果我们像这样调用上面的代码(实际上是任意值):

f(null); 
f(1);

输出将是:

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.

当你像这样做检查:typeof x === 'undefined',你本质上是在问:请检查变量x是否存在(已定义)在源代码的某个地方。(多多少少)。如果你知道c#或Java,这种类型的检查永远不会进行,因为如果它不存在,它就不会编译。

<==小提琴我==>

谁对变量=== undefined的性能增益感兴趣,可以在这里看看,但这似乎只是一个chrome优化。

http://jsperf.com/type-of-undefined-vs-undefined/30 http://jsperf.com/type-of-undefined-vs-undefined

在节点v6.9.1上,Typeof a === 'undefined'比a === 'undefined'快大约2倍。

对于未声明的变量,typeof foo将返回字符串字面量“undefined”,而标识检查foo === undefined将触发错误“foo is not defined”。

对于局部变量(您知道在某处声明了),不会发生这样的错误,因此需要进行标识符检查。