变量=== undefined vs. typeof变量=== "undefined"

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

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

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

104455 次浏览

因为undefined并不总是声明的,但是jQuery在它的main函数中声明了undefined。因此,它们在内部使用安全的undefined值,但在外部,它们使用typeof样式以确保安全。

对于未声明的变量,typeof foo将返回字符串文字"undefined",而身份检查foo === undefined将触发错误"foo未定义"

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

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

我想jQuery推荐这两种不同方法的原因是,它们在jQuery代码所在的函数中定义了自己的undefined变量,因此在该函数中undefined是安全的,不会受到外部的篡改。我还可以想象,在某个地方有人已经对这两种不同的方法进行了基准测试,并发现foo === undefined更快,因此决定采用这种方法。[更新:如评论中所述,与undefined的比较也略短,这可能是一个考虑因素。]然而,在实际情况下的增益将是完全微不足道的:这个检查永远不会成为任何类型的瓶颈,而你失去的是重大的:计算宿主对象的属性进行比较可能会抛出错误,而typeof检查永远不会。

以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检查。

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

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

typeof variable的结果不能。

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

< p > 15.1.1全局对象的值属性 < br > […]< br > 15.1.1.3未定义 < br > undefined的值是未定义的(参见8.1)。该属性的属性为
{[[可写]]:假的,[[可]]:假的,[[可]]:假}。< / p >

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

(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")

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

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

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

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

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

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,这种类型的检查永远不会进行,因为如果它不存在,它就不会编译。

<== Fiddle Me ==>

简介:

在全局作用域中,如果变量未声明或值为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);

因为在全局作用域中,我们不能100%确定是否声明了一个变量,这可能会给我们一个referenceError。当我们对未知变量使用typeof操作符时,如果变量未声明,则不会出现此问题:

var globalVar1;


console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

这是因为当变量未声明或当前值为undefined时,typeof操作符将返回字符串undefined,而这正是我们想要的。


  • 对于局部变量,我们就没有这个问题,因为我们事先知道这个变量是存在的。如果变量存在,我们可以简单地在相应的函数中查找。
  • 对于对象属性,我们就不会有这个问题,因为当我们试图查找一个不存在的对象属性时,我们也会得到值undefined

var obj = {};


console.log(obj.myProp === undefined);

“未定义”的含义;在JavaScript中

这个问题与变量的局部作用域和全局作用域无关,jQuery决策,等等。 undefined有两种不同的表达式和三种不同的用法,如下所示:

  1. “typeof"和“;undefined"类型:未声明且不存在的变量没有赋值,但具有"类型"的定义。如果你访问一个甚至不存在的变量,更不用说声明或初始化了,你将在访问它时生成一个REFERENCE ERROR,即使在测试undefined的基本默认值时也是如此,该值被赋给声明的变量,直到赋值为止。所以检查" typeof"在这种情况下防止此错误如下:
    // In this first test, the variable "myVariable1" does not exist yet so creates
// an error if we try and check if its assigned the default value of undefined!
if (myVariable1 === undefined) alert(true);// REFERENCE ERROR!


// Here we can elegantly catch the "undefined" type
// of the missing variable and stop the REFERENCE ERROR using "typeof".
if (typeof myVariable1 === "undefined") alert(true);// true


// Here we have declared the missing variable and notice its
// still an "undefined" type until initialized with a value.
let myVariable1;
if (typeof myVariable1 === "undefined") alert(true);// true


// Lastly, after we assign a value, the type is no longer
// "undefined" so returns false.
myVariable1 = 'hello';
if (typeof myVariable1 === "undefined") alert(true);// false

JavaScript中所有被访问但未声明的对象和类型将默认为“undefined"”类型。因此,这里的教训是先尝试检查typeof,以防止丢失变量错误!

  1. undefined原语值:所有尚未赋值的声明变量都在JavaScript中赋值为undefinedprimitve。如果你声明了一个变量,但还没有初始化它,它会被赋值为默认的原始的类型undefined。这和“未定义”不一样。类型。undefined的基本值是一个保留值,但可以改变,但这不是这里要求的。注意,这只捕获所有声明但未初始化的变量:
    let myVariable3;
if (myVariable3 === undefined) alert(true);// true


let myVariable4 = 'hello';
if (myVariable4 === undefined) alert(true);// false
  1. 对象和undefined原语:最后,对象属性的行为不像JavaScript中的变量。对象属性,当缺少时不会变成未定义的类型,而只是像上面一样为未声明的变量分配原始的 undefined。所以他们表现得像#2:
    let myObject = {};
if (myObject.myProperty === undefined) alert(true);// true

最佳实践

最后……这是一个非常好的理由,总是检查“未定义”;type和所有JavaScript代码中变量的undefined 原始的值。大多数人会说,你很少两者都需要。可能会有一天,在一个不存在的库中访问一个缺失的变量,并创建一个讨厌的JavaScript引用错误!所以我总是这样检查,并按照这个顺序,以停止JavaScript中的所有错误:

if (typeof myVariable !== "undefined" && myVariable !== undefined) {
// do something safe with myVariable!
}