如何在JavaScript中检查"undefined"?

goo*_*ate 2294 javascript undefined

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

if (window.myVariable)
Run Code Online (Sandbox Code Playgroud)

要么

if (typeof(myVariable) != "undefined")
Run Code Online (Sandbox Code Playgroud)

要么

if (myVariable) //This throws an error if undefined. Should this be in Try/Catch?
Run Code Online (Sandbox Code Playgroud)

Anu*_*rag 2566

如果您想知道变量是否已被声明而不管其值如何,那么使用in运算符是最安全的方法.考虑这个例子.

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"
Run Code Online (Sandbox Code Playgroud)

但这可能不是某些情况下的预期结果,因为变量或属性已声明但尚未初始化.使用in运算符进行更稳健的检查.

"theFu" in window; // true
"theFoo" in window; // false
Run Code Online (Sandbox Code Playgroud)

如果您有兴趣知道变量是否尚未声明或具有该值undefined,则使用typeof运算符.

if (typeof myVar !== 'undefined')
Run Code Online (Sandbox Code Playgroud)

typeof操作是保证返回一个字符串.直接比较undefinedundefined可以覆盖的麻烦.

window.undefined = "omg";
"omg" == undefined // true
Run Code Online (Sandbox Code Playgroud)

正如@CMS指出的那样,这已在ECMAScript第5版中修补,并且undefined是不可写的.

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

false
0
""
NaN
null
undefined

感谢@CMS指出你的第三种情况 - if (myVariable)在两种情况下也会抛出错误.第一个是没有定义抛出a的变量ReferenceError.

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 
Run Code Online (Sandbox Code Playgroud)

另一种情况是定义了变量,但是有一个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?
}
Run Code Online (Sandbox Code Playgroud)

  • `undefined`在_modern browsers_中是不可变的.设置`window.undefined`什么都不做. (53认同)
  • @Anurag,如果`myVariable`没有*声明*,第三种情况会抛出一个`ReferenceError` (8认同)
  • 可以重新定义"typeof"吗? (7认同)
  • @Anurag,很受欢迎,因为你谈到ES5,也许值得一提的是[`undefined`](http://ecma262-5.com/ELS5_HTML.htm#Section_15.1.1.3)现在被描述为非可写,不可配置且不可枚举.所以,`window.undefined ="omg";`将无声地失败或在严格模式下抛出. (5认同)
  • typeof是一种语言语句,不能重新定义if/else/while/for/function等. (4认同)
  • 我可以问一件事,为什么有人要定义每次都会引发异常的吸气剂?我想念什么吗?有人想滥用`defineProperty`是否是一个极端案例? (2认同)

Tho*_*ing 1092

我个人用

myVar === undefined
Run Code Online (Sandbox Code Playgroud)

警告:请注意,它已被===使用==并且myVar之前已声明(未定义).


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

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

凉.我知道这个.然后,Javascript中的大多数变量都可以重新定义.你永远不应该使用任何可以重新定义的内置标识符吗?

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

问题是,为了在JS中进行大量实际工作,开发人员需要依赖可重定义的标识符来实现它们.我没有听到有人告诉我我不应该使用,setTimeout因为有人可以

window.setTimeout = function () {
    alert("Got you now!");
};
Run Code Online (Sandbox Code Playgroud)

最重要的是,"可以重新定义"的论点是不使用原始=== undefined是假的.

(如果您仍然害怕undefined被重新定义,为什么要盲目地将未经测试的库代码集成到您的代码库中?甚至更简单:一个linting工具.)


此外,与该typeof方法一样,此技术可以"检测"未声明的变量:

if (window.someVar === undefined) {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

但这两种技术都在其抽象中泄漏.我劝你不要使用这个甚至是

if (typeof myVar !== "undefined") {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

考虑:

var iAmUndefined;
Run Code Online (Sandbox Code Playgroud)

要捕获是否声明了该变量,您可能需要求助于in运算符.(在许多情况下,您只需阅读代码O_o).

if ("myVar" in window) {
    doSomething();
}
Run Code Online (Sandbox Code Playgroud)

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

  • "undefined"可能被重新定义的可能性稍微大一点,因为人们确实将它用于此类检查.有些人在进行此类检查时习惯性地将常量放在左侧:`if(undefined == someVariable)`.它只需要一个拼写错误就可以默默地重新定义`undefined`:`if(undefined = someVariable)`. (50认同)
  • 我从不在LHS上编写具有"未定义"的代码.即使我这样做,我使用`===`而不是`==`的事实使得拼写错误极不可能.但是`==`不正确的事实更让人担心.无论如何,这样的bug通常很容易找到.有点像这个bug:`typeof x =="undefned"`. (49认同)
  • 怎么可能被赞成41次,它根本不起作用.如果`myVar`确实未定义,代码将抛出错误,并且很容易测试 - http://jsfiddle.net/WcM5g/正确的方法是`typeof myVar ==='undefined'`. (34认同)
  • @Laurent:开玩笑吧?这假设变量以某种方式或其他方式声明,例如通过`var`关键字或函数参数.在我(故意)编写试图以任何方式对未声明变量进行操作的代码之前,我会卖掉自己的灵魂.请记住,未声明和未定义是JS中的两个不同概念. (33认同)
  • @Andy在C(和C++)中,为了避免拼写错误,反转这样的操作数是常见的和良好的做法.`if(NULL = myVar)`无法编译并立即被捕获,而`if(myVar = NULL)`创建一个可能难以跟踪的错误,具体取决于其他代码是什么.现代编译器应该给你一个警告,但许多有经验的C程序员已经养成了交换命令的习惯. (11认同)
  • @GrandOpener:`-Wall -Werror`.QED.现在,代码不必像Voynich手稿中的内容那样阅读. (5认同)
  • @ThomasEding,一些库通过首先检查变量是否存在来定义命名空间,如果不存在则创建它(例如参见http://blog.arc90.com/2008/06/06/an-easy-way-to-实现-names-in-javascript /),并执行类似`if(ns === undefined)ns = {};`的操作不起作用.如果变量已经声明,那么确实没问题. (4认同)
  • 在未声明的变量上出错有什么问题?在大多数可编译的编程语言中,您甚至无法在未声明变量的情况下使用变量进行编译。所以我认为使用它可以消除很多错误。如果你仍然想使用一些 JS 魔术,使用带有注释的 typeof,为什么它可能是可能的,甚至没有声明变量。 (3认同)
  • @Laurent:同样,这不是唯一的方法:`if (window.ns === undefined) window.ns = {};`但我更喜欢:`if (!("ns" in window)) window.ns = {};` 虽然不可否认,我通常编写这种代码不是为了命名空间,而是为了方法: `if (!Array.prototype.map) Array.prototype.map = ...` (也是 5 年旧的 JS 文章很难说是最先进的,尽管我确信不缺少确切的代码序列。) (2认同)
  • @ThomasEding,我认为我们实际上是一致的。我最初的反应只是上面的代码*本身*(即先前未在任何地方声明“ myVar”)将不起作用。但是,如果确实已经声明了该变量,并且程序员确实*确信*已声明该变量,则您的代码绝对正确。我不太担心将“ undefined”设置为不同的值,因为无论如何,这样的环境都可能会超出拯救范围。 (2认同)
  • 如果你担心未定义被重新定义,只需要做```myVar === void 0``` (2认同)
  • @ThomasEding 你的回答和评论非常实用,对讨论很有用。但有一件事 - 请注意“我从不写……”,因为您的图书馆和团队成员可能不那么有纪律! (2认同)
  • @TimDown 是的,我当然希望没有人有在任何编程语言中将 null 或 undefined 放在 lhs 上的奇怪习惯! (2认同)
  • 赞同两者:优雅和实用主义.如果你真的,真的,真的无法获得睡眠,知道'undefined`可能不是它应该是什么,请用[IIFE]包装你的代码(https://en.wikipedia.org/wiki/Immediately- invoked_function_expression)如下:`(function(undefined){if(isItOrNot === undefined)doSomething();})();`. (2认同)

Tim*_*own 178

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

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

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}
Run Code Online (Sandbox Code Playgroud)

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

Jac*_*kin 62

你需要使用typeof.

if (typeof something != "undefined") {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • Mathias:在这里使用严格或非严格的比较是个人品味的问题.两者都将始终有效,而且两者都不正确.它可能取决于您的默认位置是否始终使用严格比较,除非特别要求类型强制(例如Crockford建议)或者您是否更喜欢使用非严格比较,除非需要严格性. (13认同)
  • 或者只是'某些东西!== undefined`,假设你已经做过`var undefined`,小心谨慎. (7认同)
  • 很高兴看到你现在添加了引号.但是,如[我的回答](http://stackoverflow.com/questions/2985771/how-to-check-for-undefined-in-javascript/2985784#2985784)中所述,请注意严格比较(`!==在这种情况下,`)不是必需的,因为`typeof`将始终返回一个字符串. (3认同)
  • 这是不准确的。你绝对不需要*使用“typeof”。 (2认同)

Zen*_*xer 43

更新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
}
Run Code Online (Sandbox Code Playgroud)

差异可以忽略不计.但是,这段代码更加简洁,一目了然,知道具体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;
Run Code Online (Sandbox Code Playgroud)

结果如下:

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
Run Code Online (Sandbox Code Playgroud)

请注意,第一行以毫秒为单位,而第二行以纳秒为单位.相差3.4纳秒是没有的.在随后的测试中,时间非常一致.


Guf*_*ffa 21

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

您可以检查变量的类型:

if (typeof(something) != "undefined") ...
Run Code Online (Sandbox Code Playgroud)

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

if (something) {
  something(param);
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我知道它*与括号一起工作*,这是因为这里的括号形成了分组运算符,它只是评估并返回里面的操作数.我只是说他们没必要. (17认同)
  • 不需要括号:`typeof`是一个运算符,而不是一个函数. (13认同)
  • @Tim - 它可以两种方式使用. (5认同)

Mat*_*ens 17

if (typeof foo == 'undefined') {
 // Do something
};
Run Code Online (Sandbox Code Playgroud)

请注意,!==在这种情况下不需要strict comparison(),因为它typeof总是返回一个字符串.

  • 我没有遇到一个无法处理`if(){}`而没有```的minifier.你指的是哪个缩小器?你说这是你如何结束所有其他声明......我猜这是真的.但是,块语句`{}`已经是它自己的语句.在技​​术上,添加`;`使它成为两个语句.从语法上讲,它是多余的.即使是自动分叉插入也不会在那里添加分号... (8认同)
  • 什么是分号(`};`)? (3认同)
  • @Gumbo,对不起,我的意思是:"分号服务的目的是什么?" (3认同)
  • @JP:大括号后面的分号只是一个空语句。 (2认同)
  • @JP:我想在阅读[Packer文档](http://dean.edwards.name/packer/usage/sample.html)之后,我几年前就开始这么做了.Packer在`function(){}`声明之后需要分号.你是对的 - 显然在'if`陈述之后不需要它,但不知怎的,我仍然认为它是有道理的. (2认同)

drz*_*aus 17

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

(请注意,在作用域包装器中使用varfor 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;
    }
})();
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*ijn 15

本文中,我读到像Underscore.js这样的框架使用这个函数:

function isUndefined(obj){
    return obj === void 0;
}
Run Code Online (Sandbox Code Playgroud)


Hri*_*shi 12

就个人而言,我总是使用以下内容:

var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}
Run Code Online (Sandbox Code Playgroud)

window.undefined属性在所有现代浏览器(JavaScript 1.8.5或更高版本)中都是不可写的.从Mozilla的文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined,我看到:使用typeof()的一个原因是它不会抛出错误变量尚未定义.

我更喜欢使用的方法

x === undefined 
Run Code Online (Sandbox Code Playgroud)

因为如果之前没有声明x,它会失败并在我的脸上爆炸,而不是默默地传递/失败.这提醒我x未声明.我相信应该声明JavaScript中使用的所有变量.


Jos*_*iel 10

我知道检查的最可靠的方法undefined是使用void 0.

这与较新的和较旧的浏览器兼容,window.undefined在某些情况下不能像can 一样被覆盖.

if( myVar === void 0){
    //yup it's undefined
}
Run Code Online (Sandbox Code Playgroud)

  • 绝对正确,但我想如果`undefined !== void 0`,您可能在上述代码库中存在其他严重问题。 (2认同)

小智 6

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

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

}
Run Code Online (Sandbox Code Playgroud)


anm*_*rti 5

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

if (typeof variable_name.value === 'undefined') {
    // variable_name is undefined
}
Run Code Online (Sandbox Code Playgroud)


Vik*_*kas 5

与@Thomas Eding 的回答相反:

myVar如果我忘记在代码中声明,那么我会得到myVar is not defined.

让我们举一个真实的例子:

我有一个变量名,但我不确定它是否在某处声明。

那么@Anurag 的回答将会有所帮助:

var myVariableToCheck = 'myVar';
if (window[myVariableToCheck] === undefined)
    console.log("Not declared or declared, but undefined.");

// Or you can check it directly 
if (window['myVar'] === undefined) 
    console.log("Not declared or declared, but undefined.");
Run Code Online (Sandbox Code Playgroud)

  • 那么,得到这样的“myVar is not Defined”错误将是一件“好事”,特别是当您专门写“如果我*忘记*声明”时[强调我的]。我喜欢在代码运行之前出现错误。如果您想了解我对您的答案的更多看法,我已经在我的答案下发表了相关评论。 (2认同)