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? |
如果您有兴趣了解某个变量是否已声明,而不管其值如何,那么使用
1 2 3 | // global scope var theFu; // theFu has been declared, but its value is undefined typeof theFu; //"undefined" |
但在某些情况下,这可能不是预期的结果,因为变量或属性已声明但未初始化。使用
1 2 | "theFu" in window; // true "theFoo" in window; // false |
如果您想知道变量是否尚未声明或值为
1 | if (typeof myVar !== 'undefined') |
保证
1 2 | window.undefined ="omg"; "omg" == undefined // true |
正如@cms指出的,这已经在ecmascript第5版中进行了修补,并且
1 2 3 4 5 6 | false 0 "" NaN null undefined |
感谢@cms指出,您的第三个案例-
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 |
警告:请注意,
我不喜欢
现在有些人读到这篇文章会痛不欲生,大喊:"等等!哇!!!!可以重新定义
酷。我知道这一点。同样,可以重新定义javascript中的大多数变量。您应该永远不要使用任何可以重新定义的内置标识符吗?
如果你遵守这条规则,对你有好处:你不是伪君子。
问题是,为了在JS中完成大量的实际工作,开发人员需要依赖可重新定义的标识符。我听不到有人告诉我不应该使用
1 2 3 | window.setTimeout = function () { alert("Got you now!"); }; |
归根结底,不使用原始
(如果您仍然害怕
此外,与
1 2 3 | if (window.someVar === undefined) { doSomething(); } |
但这两种技术的抽象性都存在漏洞。我劝你不要用这个甚至
1 2 3 | if (typeof myVar !=="undefined") { doSomething(); } |
考虑:
1 | var iAmUndefined; |
要了解该变量是否已声明,您可能需要使用
1 2 3 | if ("myVar" in window) { doSomething(); } |
但是等等!还有更多!如果一些原型链魔法正在发生…?现在,即使是上级的
使用
1 2 3 4 5 6 7 | if (typeof someUndeclaredVariable =="undefined") { // Works } if (someUndeclaredVariable === undefined) { // Throws an error } |
你需要使用
1 2 3 | if (typeof something !="undefined") { // ... } |
更新日期:2018-07-25
这篇文章刚发表已经将近五年了,而JavaScript已经走了很长的路。在重复原岗位的测试时,我发现以下测试方法之间没有一致性差异:
abc === undefined abc === void 0 typeof abc == 'undefined' typeof abc === 'undefined'
即使当我修改测试以防止Chrome优化它们时,这些差异也是微不足道的。因此,为了清楚起见,我现在建议使用
- 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中,以下测试比
1 2 3 | if (abc === void 0) { // Undefined } |
差异可以忽略不计。然而,对于知道
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/
(注意,在作用域包装中,使用
参考代码:
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 }; |
注意,在这种情况下不需要进行严格的比较(
在本文中,我了解到像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中使用的所有变量。
我知道检查
这与新的和旧的浏览器兼容,类似,在某些情况下不能像
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相反,答案是:
如果我忘记在代码中声明
让我们举一个真正的例子:
我有一个变量名,但我不确定它是否在某个地方声明。
那么@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!") })() |
当然,您可以使用