题 如何在JavaScript中检查“undefined”? [重复]


这个问题在这里已有答案:

在JavaScript中测试变量是否未定义的最合适方法是什么?我见过几种可能的方法:

if (window.myVariable)

要么

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

要么

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

1875
2017-08-02 17:53


起源


你想检查吗? 只要  undefined, 要么 null 还有? - Nick Craver♦
检查一下 stackoverflow.com/questions/27509/... - Amr Badawy
@Robert - 这个问题有一个公认的答案,答案在这里被证明是错误的 - Daniel Schaffer
看到: 如何检查javascript中的undefined?,和 变量是否未定义 和 如何在javascript中处理'undefined' - Shog9♦
这个“重复”是关于对象属性的,所以有些答案不适用于这个问题,询问变量。 - DCShannon


答案:


如果您想知道变量是否已被声明而不管其值如何,那么使用 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指出的那样,这已经在ECMAScript第5版中修补了 undefined 是不可写的。

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

假
0
“”
为NaN
空值
未定义

感谢@CMS指出你的第三个案例 - if (myVariable) 也可以在两种情况下抛出错误。第一个是没有定义抛出a的变量 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?
}

2158
2017-08-02 17:58



@Anurag,第三个案例将抛出一个 ReferenceError 如果 myVariable 不是 声明... - CMS
@Anurag,很受欢迎,因为你谈到ES5,也许值得一提 undefined现在被描述为不可写,不可配置和不可枚举。所以, window.undefined = "omg"; 只会无声地失败或在严格模式下投掷。 - CMS
可以重新定义“typeof”吗? - CHI Coder 007
typeof是一种语言语句,除了if / else / while / for / function等之外,它不能重新定义。 - MooGoo
undefined 是不变的 现代浏览器。设置 window.undefined 什么也没做。 - Paul S.


我个人用

myVar === undefined

警告:请注意 === 被用完了 == 然后 myVar 以前是 声明 (不 定义)。


我不喜欢 typeof myVar === "undefined"。我认为这是漫长的啰嗦和不必要的。 (我可以用更少的代码完成相同的工作。)

现在有些人在读到这篇文章时会痛苦地说话,尖叫道:“等等!等一下! 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 (和****咳嗽**** typeof)工作得很好。如果你真的在乎,你可以自己阅读这个主题。)


888
2017-08-02 18:26



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


运用 typeof 是我的偏好。从未声明变量时它将起作用,与之不同的是 == 要么 === 运营商或类型强制使用 if。 (undefined不像 null,也可以在ECMAScript 3环境中重新定义,使其不可靠进行比较,尽管几乎所有常见环境现在都符合ECMAScript 5或更高版本)。

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

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

149
2017-08-02 18:05



您可能想要检查是否已经定义了表示某个功能的特定全局变量。例如,库代码可能希望检查先前尚未包含库。 - Tim Down
窗口中的'xyz'或者自我中的'xyz'要好得多 - Jamie Pate
@JamiePate:为了清楚起见,我不同意这一点 'xyz' in window 是比一个更好的答案 typeof xyz == "undefined" 因为它正在测试错误的东西。该 in 运算符检查属性的存在,无论其值如何,而问题至少似乎是询问如何测试变量的值是否为 undefined。或许我可以选择一个更好的例子 var foo; "foo" in window;这会返回true foo 肯定是未定义的。 - Tim Down
@JamiePate:为什么 xyz === undefined 比...更好 typeof xyz == "undefined"?同意全局,但我们两个人只有你一直建议检查属性 window。 - Tim Down
在大多数情况下它是多余的(并且可读性较差)。如果您知道xyz是声明的变量,为什么要经历额外的麻烦?在某些浏览器中,类型检查和字符串比较要慢得多,所以如果你在紧密循环中做很多事情就会失去一些性能。 jsperf.com/type-of-undefined-vs-undefined/6 - Jamie Pate


你需要使用 typeof 。

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

51
2018-06-06 20:22



要不就 something !== undefined,假设你已经完成了 var undefined,谨慎。 - James
很高兴看到你现在添加了引号。但是,如上所述 我的答案,请注意严格比较(!==在这种情况下,没有必要,因为 typeof 将始终返回一个字符串。 - Mathias Bynens
Mathias:在这里使用严格或非严格的比较是个人品味的问题。两者都将始终有效,而且两者都不正确。它可能取决于您的默认位置是否始终使用严格比较,除非特别要求类型强制(例如,Crockford建议)或者您是否更喜欢使用非严格比较,除非需要严格。 - Tim Down


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

您可以检查变量的类型:

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

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

if (something) {
  something(param);
}

20
2018-06-06 20:23



不需要括号: typeof 是一个运算符,而不是一个函数。 - Tim Down
@Tim - 它可以两种方式使用。 - Nick Craver♦
@Tim:@Nick是对的。看到 developer.mozilla.org/en/Core_Javascript_1.5_Reference/... - Mathias Bynens
是的,我知道 作品 使用括号,这是因为这里的括号形成了分组运算符,它只是计算并返回内部的操作数。我只是说他们没必要。 - Tim Down


一些场景说明了各种答案的结果: 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

17
2018-01-13 15:39



注意使用 undefined 在范围包装器内;这不仅可以防止(不寻常)“哦,但是 undefined 可以重新定义“但也有助于'缩小。 - drzaus


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

请注意严格比较(!==在这种情况下,没有必要,因为 typeof 将始终返回一个字符串。


16
2018-06-06 20:26



什么是分号(};)? - James
@ J-P:结束括号后的分号只是一个空语句。 - Gumbo
@Gumbo,对不起,我的意思是:“分号服务的目的是什么?” - James
我没有遇到无法处理的缩放器 if(){} 没有 ; 你指的是哪种缩小器?你说这就是你如何结束所有其他陈述......我猜这是真的。但是,一个块声明 {} 已经是一个自己的声明。添加一个 ; 从技术上讲,它是两个陈述。从语法上讲,它是多余的。即使是自动分叉插入也不会在那里添加分号... - James
@ J-P:我想我几年前读完后就开始做了 Packer文档。 Packer预计会有分号 function() {} 声明。你是对的 - 显然它不是必需的 if 陈述,但不知怎的,我仍然认为这是有道理的。 - Mathias Bynens


本文 我读过像这样的框架 Underscore.js 使用此功能:

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

15
2017-12-19 10:42





我知道检查的最可靠方式 undefined 是用 void 0

这与新旧浏览器兼容,类似,并且不能被覆盖 window.undefined 在某些情况下可以。

if( myVar === void 0){
    //yup it's undefined
}

9
2018-02-19 13:20



这被低估了,恕我直言是检查未定义的东西的首选方法。 - Brian M. Hunt
绝对正确,但我想如果 undefined !== void 0,您可能在所述代码库中有其他严重问题。 - Thomas Eding