如果JavaScript中未定义变量,最合适的测试方法是什么?

我见过几种可能的方法:

if (window.myVariable)

Or

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

Or

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

如果您想知道变量是否尚未声明或值未定义,请使用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?
}

其他回答

更新2018-07-25

自从这篇文章发表以来,已经将近五年了,JavaScript已经取得了长足的进步。在重复原始帖子中的测试时,我发现以下测试方法之间没有一致的差异:

abc==未定义abc==无效0typeof abc==“未定义”abc类型==“未定义”

即使当我修改测试以防止Chrome优化它们时,差异也微不足道。因此,为了清楚起见,我现在建议abc===undefined。

相关内容来自chrome://version:

谷歌Chrome:67.0.3396.99(官方版本)(64位)(队列:稳定)修订:a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b参考/分支头/3396@{#790}操作系统:WindowsJavaScript:V8 6.7.288.46用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,类似Gecko)Chrome/67.03396.99 Safari/537.36

原帖子2013-11-01

在Google Chrome中,以下测试比一种测试速度稍快:

if (abc === void 0) {
    // Undefined
}

差异可以忽略不计。然而,这段代码更加简洁,对于了解void 0含义的人来说一目了然。然而,请注意,abc仍然必须声明。

typeof和void都明显快于直接与undefined进行比较。我在Chrome开发者控制台中使用了以下测试格式:

var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

结果如下:

Test: | abc === undefined      abc === void 0      typeof abc == 'undefined'
------+---------------------------------------------------------------------
x10M  |     13678 ms               9854 ms                 9888 ms
  x1  |    1367.8 ns              985.4 ns                988.8 ns

请注意,第一行以毫秒为单位,而第二行以纳秒为单位。3.4纳秒的差异并不重要。在随后的测试中,时间相当一致。

我个人使用

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%的时间里,==未定义(和***咳嗽***类型)工作正常。如果你真的关心,你可以单独阅读这个主题。)

由于其他答案对我都没有帮助,我建议这样做。它在Internet Explorer 8中对我有效:

if (typeof variable_name.value === 'undefined') {
    // variable_name is undefined
}

您可以使用typeof,如下所示:

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

如果未定义,它将不等于包含字符“undefined”的字符串,因为该字符串未定义。

您可以检查变量的类型:

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

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

if (something) {
  something(param);
}