javascript - 如何检查"undefined"在JavaScript?

  显示原文与译文双语对照的内容

这个问题已经有了如下答案:

如果一个变量在JavaScript中未定义,最适合测试的方法是什么? 我看到了几种可能的方法:


if (window.myVariable)

或者


if (typeof(myVariable)!="undefined")

或者


if (myVariable)//This throws an error if undefined. Should this be in Try/Catch?

时间:

如果你有兴趣了解变量是否已经声明,而不管它的值如何,那么使用 in 运算符是最安全的方法。 考虑这个例子。


//global scope
var theFu;//theFu has been declared, but its value is undefined
typeof theFu;//"undefined"

但这可能不是某些情况下的预期结果,因为声明了变量或者属性,但只是未初始化。 使用 in 操作符进行更稳健的检查。


"theFu" in window;//true
"theFoo" in window;//false

如果你有兴趣知道变量是否还没有声明或者具有值 undefined,那么使用 typeof 运算符。


if (typeof myVar!= 'undefined')

typeof 运算符保证返回一个字符串。 对 undefined的直接比较很麻烦,因为 undefined 可以被覆盖。


window.undefined ="omg";
"omg" == undefined//true

就像 @CMS 指出的那样,已经在 5中修补了这一点,并且 undefined 是 non-writable 。

if (window.myVar) 也将包含这些falsy值,因此它不是很健壮:

false
0
""
NaN
null
undefined

感谢 @CMS 指出你的第三个案例- if (myVariable) 也会在两个案例中抛出一个错误。 第一个是当变量没有被定义时抛出一个 ReferenceError


//abc was never declared.
if (abc) {
//ReferenceError: abc is not defined
} 

另一种情况是定义了变量,但有一个getter函数,它在调用时抛出一个错误。 比如,


//or it's a property that can throw an error
Object.defineProperty(window,"myVariable", { 
 get: function() { throw new Error("W00t?"); }, 
 set: undefined 
});
if (myVariable) {
//Error: W00t?
}

我个人使用

 
myVar === undefined

 

警告:请注意, =====myVar 一直使用以前宣布 ( 不是定义的 ) 。


我不喜欢 typeof myVar ==="undefined" 我认为它是经过长时间的缠绕和不必要的。 ( 我可以用更少的代码实现同样的操作。)

现在有些人会在阅读时遇到痛苦,尖叫: "等等WAAITTT undefined 可以重新定义" !

酷。我知道。然后,Javascript中的大多数变量都可以重新定义。 你是否应该使用任何可以重新定义的内置标识符?

如果你遵循这里规则,你将很好: 你不是一个 hypocrite 。

问题是,为了在JS中做大量的实际工作,开发者需要依靠redefinable标识符来做他们所做的事情。 我没有听到有人告诉我我不应该使用 setTimeout,因为有人可以


window.setTimeout = function () {
 alert("Got you now!");
};

底线,不使用原始 === undefined"它可以被重新定义"参数是假的。

( 如果你仍然害怕 undefined 被重新定义,为什么你盲目地将未经测试的库代码集成到你的代码库中? 或者更简单:linting工具。


同样,与 typeof 方法一样,这里技术可以"检测"未声明的变量:


if (window.someVar === undefined) {
 doSomething();
}

但是这两种技术在它们的抽象中都有漏洞。 我强烈建议你不要使用这个或者甚至


if (typeof myVar!=="undefined") {
 doSomething();
}

请考虑:

 
var iAmUndefined;

 

要捕获该变量是否声明,你可能需要求助于 in 运算符。 ( 在很多情况下,你可以简单地阅读代码 O_o ) 。


if ("myVar" in window) {
 doSomething();
}

等等还有更多如果一些Prototype链魔法正在发生。。 ! 现在即使是高级的in 操作符也不够。 ( 好的,我已经完成了这部分,只是说,对于 99%的时间,=== undefined ( 和 ****cough**** typeof ) 可以正常工作。 如果你真的在意,你可以自己阅读这个主题。

使用 typeof 是我的首选。 当变量从未声明时,它将工作,不同于与 == 或者 === 运算符的任何比较,或者使用 if的类型强制。 ( undefinednull 不同,也可能重新定义在ecmascript 3环境中,使其不可靠的相比较而言,尽管几乎所有常见的环境现在符合ecmascript 5或以上)。


if (typeof someUndeclaredVariable =="undefined") {
//Works
}

if (someUndeclaredVariable === undefined) { 
//Throws an error
}

如果未定义,它将不等于包含字符"未定义"的字符串,因为字符串不是未定义的。

你可以检查变量的类型:


if (typeof(something)!="undefined").. .

有时你甚至不必检查类型。 如果变量的值在设置为( 例如如果它是一个函数) 时不能计算为 false,那么你只需 evalue 。 例如:


if (something) {
 something(param);
}

你需要使用 typeof


if (typeof something!="undefined") {
//...
}


if (typeof foo == 'undefined') {
//Do something
};

注意,在本例中不需要严格比较( !== ),因为 typeof 总是返回一个字符串。

一些场景展示了各种答案的结果: http://jsfiddle.net/drzaus/UVjM4/

( 注意,使用 var 进行 in 测试会在作用域包装中产生差异)

参考代码:


(function(undefined) {
 var definedButNotInitialized;
 definedAndInitialized = 3;
 someObject = {
 firstProp:"1"
, secondProp: false
//, undefinedProp not defined
 }
//var notDefined;

 var tests = [
 'definedButNotInitialized in window',
 'definedAndInitialized in window',
 'someObject.firstProp in window',
 'someObject.secondProp in window',
 'someObject.undefinedProp in window',
 'notDefined in window',

 '"definedButNotInitialized" in window',
 '"definedAndInitialized" in window',
 '"someObject.firstProp" in window',
 '"someObject.secondProp" in window',
 '"someObject.undefinedProp" in window',
 '"notDefined" in window',

 'typeof definedButNotInitialized =="undefined"',
 'typeof definedButNotInitialized === typeof undefined',
 'definedButNotInitialized === undefined',
 '! definedButNotInitialized',
 '!! definedButNotInitialized',

 'typeof definedAndInitialized =="undefined"',
 'typeof definedAndInitialized === typeof undefined',
 'definedAndInitialized === undefined',
 '! definedAndInitialized',
 '!! definedAndInitialized',

 'typeof someObject.firstProp =="undefined"',
 'typeof someObject.firstProp === typeof undefined',
 'someObject.firstProp === undefined',
 '! someObject.firstProp',
 '!! someObject.firstProp',

 'typeof someObject.secondProp =="undefined"',
 'typeof someObject.secondProp === typeof undefined',
 'someObject.secondProp === undefined',
 '! someObject.secondProp',
 '!! someObject.secondProp',

 'typeof someObject.undefinedProp =="undefined"',
 'typeof someObject.undefinedProp === typeof undefined',
 'someObject.undefinedProp === undefined',
 '! someObject.undefinedProp',
 '!! someObject.undefinedProp',

 'typeof notDefined =="undefined"',
 'typeof notDefined === typeof undefined',
 'notDefined === undefined',
 '! notDefined',
 '!! notDefined'
 ];

 var output = document.getElementById('results');
 var result = '';
 for(var t in tests) {
 if(!tests.hasOwnProperty(t) ) continue;//bleh

 try {
 result = eval(tests[t]);
 } catch(ex) {
 result = 'Exception--' + ex;
 }
 console.log(tests[t], result);
 output.innerHTML +="n" + tests[t] +":" + result;
 }
})();

和结果:


definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized =="undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized =="undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp =="undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp =="undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp =="undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined =="undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

是:你正在比较字符串而不是全局对象的undefined 属性。 相反,相反


if (something!== undefined) {
. . .
}

甚至更好:


if (typeof something!="undefined") {
. . .
}

中,本文我阅读了 Underscore.js 使用这个函数:


function isUndefined(obj){
 return obj === void 0;
}


//x has not been defined before
if (typeof x === 'undefined') {//Evaluates to true without errors.
//These statements execute.
}

if (x === undefined) {//Throws a ReferenceError

}

...