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

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

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


当前回答

使用typef -variant的另一个原因是:undefined可以被重新定义。

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

typeof变量的结果不能。

更新:注意,在ES5中不是这样的,全局未定义是一个不可配置,不可写的属性:

15.1.1全局对象的值属性 […] 15.1.1.3未定义 undefined的值是undefined(参见8.1)。该属性具有以下属性 {[[可写]]:false,[[可列举]]:false,[[可配置]]:false}。

但它仍然可以被一个局部变量遮蔽:

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

或参数:

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

其他回答

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

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

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

使用typef -variant的另一个原因是:undefined可以被重新定义。

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

typeof变量的结果不能。

更新:注意,在ES5中不是这样的,全局未定义是一个不可配置,不可写的属性:

15.1.1全局对象的值属性 […] 15.1.1.3未定义 undefined的值是undefined(参见8.1)。该属性具有以下属性 {[[可写]]:false,[[可列举]]:false,[[可配置]]:false}。

但它仍然可以被一个局部变量遮蔽:

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

或参数:

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

对于局部变量,使用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并不总是声明的,但是jQuery在它的main函数中声明了undefined。因此,它们在内部使用安全的未定义值,但在外部,它们使用typeof样式以确保安全。