如何在 JavaScript 中检查“未定义”?

IT技术 javascript undefined
2021-01-18 05:10:44

在 JavaScript 中测试变量是否未定义的最合适方法是什么?

我已经看到了几种可能的方法:

if (window.myVariable)

或者

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

或者

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

如果您想知道变量是否已被声明而不管其值如何,那么使用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

如果您想知道变量是否尚未声明或具有 value undefined,请使用typeof运算符,它保证返回一个字符串:

if (typeof myVar !== 'undefined')

直接比较比较undefined麻烦,因为undefined可以覆盖。

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

正如@CMS 所指出的,这已在 ECMAScript 第 5 版中进行了修补,并且undefined是不可写的。

if (window.myVar) 还将包括这些虚假值,因此它不是很健壮:

错误的
0
“”
NaN
空值
不明确的

感谢@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?
}
@Anurag,不客气,既然你在谈论 ES5,也许值得一提的undefined是,现在被描述为不可写、不可配置和不可枚举。因此,window.undefined = "omg";将简单地静默失败或在严格模式下抛出。
2021-03-12 05:10:44
typeof 是一个语言语句,它不能像 if/else/while/for/function 等一样被重新定义。
2021-03-12 05:10:44
“typeof”可以重新定义吗?
2021-03-18 05:10:44
@Anurag,第三种情况将抛出一个ReferenceErrorifmyVariable声明......
2021-03-30 05:10:44
undefined现代浏览器中是不可变的设置window.undefined没有任何作用。
2021-04-01 05:10:44

我个人使用

myVar === undefined

警告:请注意,===使用 over==并且myVar之前已声明未定义)。


我不喜欢typeof myVar === "undefined"我认为这是冗长且不必要的。(我可以用更少的代码完成同样的事情。)

现在有些人读到这里会痛得倒地不起,大叫:“等等!WAAITTT!!!undefined可以重新定义!”

凉爽的。我知道这个。再说一次,Javascript 中的大多数变量都可以重新定义。您是否应该永远不使用任何可以重新定义的内置标识符?

如果你遵循这条规则,对你有好处:你不是一个伪君子。

问题是,为了在 JS 中做大量实际工作,开发人员需要依赖可重新定义的标识符来实现它们的本质。我没有听到人们告诉我我不应该使用,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();
}

可是等等!还有更多!如果一些原型链魔法正在发生怎么办……?现在即使是优秀的in运营商也不够。(好吧,我已经完成了这部分的工作,只是说在 99% 的时间里,=== undefined(和 ****cough**** typeof)工作得很好。如果你真的关心,你可以阅读关于这个主题它自己的。)

@Laurent:开玩笑吧?这假设变量是以某种方式声明的,例如通过var关键字或函数参数。在我(故意)编写尝试以任何方式对未声明的变量起作用的代码之前,我会出卖我的灵魂。请记住,未声明和未定义是 JS 中的两个不同概念。
2021-03-22 05:10:44
undefined重新定义的可能性略高,因为人们确实将其用于此类检查。有些人在进行此类检查时习惯性地将常量放在左侧:if (undefined == someVariable). 只需要一个错字就可以默默地重新定义undefined: if (undefined = someVariable)
2021-03-27 05:10:44
这怎么可能被投票 41 次,它根本不起作用。如果myVar确实未定义,代码将抛出错误,并且很容易测试 - jsfiddle.net/WcM5g正确的方法是typeof myVar === 'undefined'.
2021-04-01 05:10:44
@Andy 在 C(和 C++)中,反转这样的操作数以避免拼写错误是常见且良好的做法。 if (NULL = myVar)无法编译并立即被捕获,而if (myVar = NULL)创建一个可能难以追踪的错误,具体取决于它周围的其他代码。现代编译器应该给你一个警告,但是很多有经验的 C 程序员已经养成了交换顺序的习惯。
2021-04-01 05:10:44
我从来没有写过undefinedLHS 上的代码即使我这样做了,我使用===而不是==使错字的可能性极小。==不正确的事实更令人担忧。无论如何,这样的错误通常很容易找到。有点像这个错误:typeof x == "undefned".
2021-04-03 05:10:44

2020 更新

我更喜欢typeof检查(即undefined可以重新定义)的一个原因与 ECMAScript 5 的大规模采用无关。另一个,您可以typeof用来检查未声明变量的类型,始终是小众的。因此,我现在建议在大多数情况下使用直接比较:

myVariable === undefined

2010年的原始答案

使用typeof是我的偏好。当变量从未被声明时它将起作用,这与使用=====运算符或类型强制的任何比较不同ifundefined与 不同null,它也可能在 ECMAScript 3 环境中重新定义,因此比较不可靠,尽管现在几乎所有常见环境都符合 ECMAScript 5 或更高版本)。

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

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}
@JamiePate:明确地说,我不同意这'xyz' in window是一个更好的答案,而不是typeof xyz == "undefined"因为它正在测试错误的东西。in操作者检查是否存在属性的,而不管其值的,而至少出现的问题进行询问如何测试一个变量的值是undefined也许我选择的一个更好的例子是var foo; "foo" in window这返回 true 而foo绝对未定义。
2021-03-18 05:10:44
在大多数情况下它是多余的(而且可读性较差)。如果你知道 xyz 是一个声明的变量,为什么还要经历额外的麻烦?在某些浏览器中,类型检查和字符串比较要慢得多,所以如果你在一个紧密的循环中做很多事情,你会失去一些性能。jsperf.com/type-of-undefined-vs-undefined/6
2021-03-18 05:10:44
@JamiePate:为什么xyz === undefinedtypeof xyz == "undefined"? 同意全局变量,但在我们两个中,只有您一直建议检查window.
2021-03-29 05:10:44
您可能想要检查是否已经定义了表示某项功能的特定全局变量。例如,库代码可能希望检查该库之前是否尚未被包含。
2021-04-08 05:10:44
窗口中的 'xyz' 或 self 中的 'xyz' 更好
2021-04-09 05:10:44

你可以使用typeof,像这样:

if (typeof something != "undefined") {
    // ...
}
很高兴看到您现在添加了引号。但是,正如我的回答中提到的,请注意!==在这种情况下不需要严格比较 ( ),因为typeof它将始终返回一个字符串。
2021-03-20 05:10:44
或者只是something !== undefined,假设你已经做了var undefined,预先谨慎。
2021-03-22 05:10:44
这是不准确的。你绝对不需要使用typeof.
2021-03-28 05:10:44
Mathias:这里使用严格或非严格比较是个人品味的问题。两者都将始终有效,而且两者都不正确。这可能取决于您的默认位置是否始终使用严格比较,除非特别需要类型强制(例如,Crockford 推荐),或者您是否更喜欢使用非严格比较,除非需要严格。
2021-04-02 05:10:44
哦,现在我明白你的意思了;您的评论具有误导性,因为看起来与代码的正确性有关。是的,不需要使用它,因为一切都是品味的问题;如果你知道你在做什么,你甚至不需要清理用户输入;这并不意味着应该这样做。在这种情况下,在所有答案中,使用typeof是最安全且不易出错的选项。除了写出如此令人困惑的评论之外,我还会编辑答案以使用另一个术语而不是需要“你可以|应该|更好|可能会使用typeof例如:)
2021-04-09 05:10:44

更新 2018-07-25

这篇博文从第一次发布到现在已经快五年了,JavaScript 已经走过了漫长的道路。在重复原帖中的测试时,我发现以下测试方法之间没有一致的差异:

  • abc === undefined
  • abc === void 0
  • typeof abc == 'undefined'
  • typeof abc === 'undefined'

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

相关内容来自chrome://version

  • 谷歌浏览器:67.0.3396.99(官方版本)(64 位)(队列:稳定)
  • 修订版:a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs/branch-heads/3396@{#790}
  • 操作系统:Windows
  • JavaScript:V8 6.7.288.46
  • 用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/67.0.3396.99 Safari/537.36

原帖 2013-11-01

在谷歌浏览器中,以下比typeof测试稍微快一点

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

差异可以忽略不计。但是,这段代码更简洁,对于知道void 0含义的人来说更清晰但是请注意,abc 仍然必须声明

双方typeofvoid分别显著快于对直接比较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 纳秒的差异不算什么。在随后的测试中,时间非常一致。

将您的方法添加到我的测试列表中,它确实检查了(不是我怀疑您)-- jsfiddle.net/drzaus/UVjM4/8
2021-03-22 05:10:44
哇,太令人心碎了,这是-1;我花了很多时间对此进行测试。那好吧。这是很好的信息,所以我会把它留在这里。记住,不要===用来测试undefined
2021-03-30 05:10:44
我认为 -1 是因为 1) <q>对于知道 void 0 意味着什么的人来说更清晰</q>,因为void 0对我来说听起来更不寻常,2) 你应该分享你的性能测试,但主要是3)abc === void 0如果abc未定义,您的第一个示例 ( ) 将引发异常
2021-04-03 05:10:44
我发现 undefined 比较比 void 0 慢,这很令人惊讶。我想运行的 JS 版本足够新,可以保证 undefined 是恒定的。好难过。
2021-04-03 05:10:44
考虑到这些数字(来自前一段时间),我认为清晰度和速度之间的最佳折衷是typeof测试。
2021-04-06 05:10:44