如果JavaScript中未定义变量,最合适的测试方法是什么?
我见过几种可能的方法:
if (window.myVariable)
Or
if (typeof(myVariable) != "undefined")
Or
if (myVariable) // This throws an error if undefined. Should this be in Try/Catch?
如果JavaScript中未定义变量,最合适的测试方法是什么?
我见过几种可能的方法:
if (window.myVariable)
Or
if (typeof(myVariable) != "undefined")
Or
if (myVariable) // This throws an error if undefined. Should this be in Try/Catch?
当前回答
我个人使用
myVar === undefined
警告:请注意==用于==,并且myVar先前已声明(未定义)。
我不喜欢myVar==“undefined”的类型。我认为这是长篇大论,没有必要。(我可以用更少的代码完成同样的任务。)
现在有些人读到这篇文章时,会痛苦万分,尖叫道:“等等!WAAITT!!!undefined可以被重新定义!”
凉的我知道这一点。同样,Javascript中的大多数变量都可以重新定义。你应该永远不要使用任何可以重新定义的内置标识符吗?
如果你遵循这条规则,对你有好处:你不是伪君子。
问题是,为了在JS中做大量的实际工作,开发人员需要依赖于可重新定义的标识符。我没有听到有人告诉我我不应该使用setTimeout,因为有人可以
window.setTimeout = function () {
alert("Got you now!");
};
总之,不使用原始==undefined的“它可以被重新定义”参数是假的。
(如果您仍然害怕未定义被重新定义,为什么要盲目地将未经测试的库代码集成到代码库中?或者更简单:一个linting工具。)
此外,与typeof方法一样,该技术可以“检测”未声明的变量:
if (window.someVar === undefined) {
doSomething();
}
但这两种技术在抽象方面都存在漏洞。我劝你不要用这个甚至
if (typeof myVar !== "undefined") {
doSomething();
}
考虑:
var iAmUndefined;
要获取该变量是否已声明,可能需要使用in运算符。(在许多情况下,您可以简单地读取代码O_O)。
if ("myVar" in window) {
doSomething();
}
但是等等!还有更多!如果一些原型连锁魔法正在发生…?现在,即使是高级操作员也不够。(好吧,我已经完成了这一部分的工作,只是说99%的时间里,==未定义(和***咳嗽***类型)工作正常。如果你真的关心,你可以单独阅读这个主题。)
其他回答
在本文中,我了解到Undercore.js等框架使用此函数:
function isUndefined(obj){
return obj === void 0;
}
说明各种答案结果的一些场景:http://jsfiddle.net/drzaus/UVjM4/
(请注意,在测试中使用var会在作用域包装器中产生差异)
参考代码:
(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
由于其他答案对我都没有帮助,我建议这样做。它在Internet Explorer 8中对我有效:
if (typeof variable_name.value === 'undefined') {
// variable_name is undefined
}
您可以使用typeof,如下所示:
if (typeof something != "undefined") {
// ...
}
如果您有兴趣了解变量是否已声明,而不管其值如何,那么使用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
如果您想知道变量是否尚未声明或值未定义,请使用typeof运算符,它保证返回字符串:
if (typeof myVar !== 'undefined')
与undefined的直接比较很麻烦,因为undefineed可以被覆盖。
window.undefined = "foo";
"foo" == undefined // true
正如@CMS所指出的,这已经在ECMAScript第5版中修补,undefined是不可写的。
if(window.myVar)也将包含这些虚假值,因此它不是很健壮:
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?
}