如何检查javascript中的”未定义”“undefined” ?

How to check for “undefined” in JavaScript?

本问题已经有最佳答案,请猛点这里访问。

如果一个变量在javascript中未定义,那么最合适的测试方法是什么?我看到了几种可能的方法:

1
if (window.myVariable)

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

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


如果您有兴趣了解某个变量是否已声明,而不管其值如何,那么使用in运算符是最安全的方法。考虑这个例子。

1
2
3
// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; //"undefined"

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

1
2
"theFu" in window; // true
"theFoo" in window; // false

如果您想知道变量是否尚未声明或值为undefined,那么使用typeof运算符。

1
if (typeof myVar !== 'undefined')

保证typeof运算符返回字符串。直接与undefined比较很麻烦,因为undefined可以被覆盖。

1
2
window.undefined ="omg";
"omg" == undefined // true

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

if (window.myVar)也将包括这些不稳定的价值观,因此它不是很稳健:

1
2
3
4
5
6
false
0
""
NaN
null
undefined

感谢@cms指出,您的第三个案例-if (myVariable)也可能在两个案例中引发错误。第一种情况是变量没有被定义,它会抛出一个ReferenceError

1
2
3
4
// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
}

另一种情况是定义了变量,但具有getter函数,该函数在调用时抛出错误。例如,

1
2
3
4
5
6
7
8
// 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?
}


我个人使用

1
myVar === undefined

警告:请注意,===用于==myVar以前已声明(未定义)。

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

现在有些人读到这篇文章会痛不欲生,大喊:"等等!哇!!!!可以重新定义undefined

酷。我知道这一点。同样,可以重新定义javascript中的大多数变量。您应该永远不要使用任何可以重新定义的内置标识符吗?

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

问题是,为了在JS中完成大量的实际工作,开发人员需要依赖可重新定义的标识符。我听不到有人告诉我不应该使用setTimeout,因为有人可以

1
2
3
window.setTimeout = function () {
    alert("Got you now!");
};

归根结底,不使用原始=== undefined的"它可以重新定义"论点是伪造的。

(如果您仍然害怕undefined被重新定义,为什么您盲目地将未测试的库代码集成到您的代码库中?或者更简单:一个起毛工具。)

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

1
2
3
if (window.someVar === undefined) {
    doSomething();
}

但这两种技术的抽象性都存在漏洞。我劝你不要用这个甚至

1
2
3
if (typeof myVar !=="undefined") {
    doSomething();
}

考虑:

1
var iAmUndefined;

要了解该变量是否已声明,您可能需要使用in运算符。(在许多情况下,您可以简单地阅读代码o_o)。

1
2
3
if ("myVar" in window) {
    doSomething();
}

但是等等!还有更多!如果一些原型链魔法正在发生…?现在,即使是上级的in操作符也不够。(好吧,这部分我已经做完了,除了99%的时间里,=== undefined(和**咳嗽*typeof)工作得很好。如果你真的很在意,你可以自己阅读这个主题。)


使用typeof是我的首选。与=====运算符或使用if的类型强制相比,变量从未声明时,它将起作用。(与null不同,undefined也可以在ecmascript 3环境中重新定义,使其不可靠,尽管现在几乎所有常见环境都符合ecmascript 5或更高版本)。

1
2
3
4
5
6
7
if (typeof someUndeclaredVariable =="undefined") {
    // Works
}

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


你需要使用typeof

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


更新日期:2018-07-25

这篇文章刚发表已经将近五年了,而JavaScript已经走了很长的路。在重复原岗位的测试时,我发现以下测试方法之间没有一致性差异:

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

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

chrome://version相关内容:

  • Google Chrome:67.0.3396.99(官方版本)(64位)(队列:稳定)
  • 修订版:A337FBF3C2AB8EBC6B64B0BFDCE73A20E252B参考/分支机构负责人/3396@790
  • 操作系统:窗口
  • 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

在Google Chrome中,以下测试比typeof测试快得多:

1
2
3
if (abc === void 0) {
    // Undefined
}

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

typeofvoid均明显快于直接与undefined比较。我在Chrome开发者控制台中使用了以下测试格式:

1
2
3
4
5
6
7
8
9
var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

结果如下:

1
2
3
4
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纳秒的差异是什么都不是。在随后的测试中,时间是相当一致的。


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

您可以检查变量的类型:

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

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

1
2
3
if (something) {
  something(param);
}


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

(注意,在作用域包装中,使用var进行in测试会产生差异)

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
(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 +="
"
+ tests[t] +":" + result;
    }
})();

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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


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

注意,在这种情况下不需要进行严格的比较(!==,因为typeof总是返回一个字符串。


在本文中,我了解到像underline.js这样的框架使用以下函数:

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

就我个人而言,我总是使用以下方法:

1
2
3
4
5
6
7
var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}

window.undefined属性在所有现代浏览器(javascript 1.8.5或更高版本)中都是不可写的。从Mozilla的文档:https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/undefined,我看到了这一点:使用typeof()的一个原因是,如果没有定义变量,它不会抛出错误。

我更喜欢使用

1
x === undefined

因为它失败了,在我的脸上爆炸,而不是无声地通过/失败,如果X之前没有被宣布。这会提醒我X未声明。我认为应该声明JavaScript中使用的所有变量。


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

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

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


既然其他答案都没有帮助我,我建议你这样做。它在Internet Explorer 8中为我工作:

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

1
2
3
4
5
6
7
8
// x has not been defined before
if (typeof x === 'undefined') { // Evaluates to true without errors.
   // These statements execute.
}

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

}

与@thomas eeding相反,答案是:

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

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

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

那么@anurag的回答将有助于:

1
2
3
4
5
6
7
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.");


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    var x;
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    if (typeof y ==="undefined") {
        alert ("I am not even declared.")
    };

    /* One more thing to understand: typeof ==='undefined' also checks
       for if a variable is declared, but no value is assigned. In other
       words, the variable is declared, but not defined. */


    // Will repeat above logic of x for typeof === 'undefined'
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    /* So typeof === 'undefined' works for both, but x === undefined
       only works for a variable which is at least declared. */


    /* Say if I try using typeof === undefined (not in quotes) for
       a variable which is not even declared, we will get run a
       time error. */


    if (z === undefined) {
        alert ("I am neither declared nor defined.")
    };
    // I got this error for z ReferenceError: z is not defined

我使用它作为函数参数,并在函数执行时排除它,这样我就得到了未定义的"real"。尽管它确实要求您将代码放入函数中。我在读取jquery源代码时发现了这个。

1
2
3
4
5
6
7
undefined = 2;

(function (undefined) {
   console.log(undefined); // prints out undefined
   // and for comparison:
   if (undeclaredvar === undefined) console.log("it works!")
})()

当然,您可以使用typeof。但无论如何,我的所有代码通常都在一个包含函数内,所以使用这个方法可能会在这里和那里为我节省一些字节。