如何检查 JavaScript 中的“未定义”? [复制]
Posted
技术标签:
【中文标题】如何检查 JavaScript 中的“未定义”? [复制]【英文标题】:How can I check for "undefined" in JavaScript? [duplicate] 【发布时间】:2011-02-28 11:17:20 【问题描述】:在 javascript 中测试变量是否未定义最合适的方法是什么?
我已经看到了几种可能的方法:
if (window.myVariable)
或者
if (typeof(myVariable) != "undefined")
或者
if (myVariable) // This throws an error if undefined. Should this be in Try/Catch?
【问题讨论】:
您要只检查undefined
,还是同时检查null
?
查看***.com/questions/27509/…
@Robert - 这个问题有一个公认的答案,这里的答案被证明是错误的
参见:How to check for undefined in javascript?、whether a variable is undefined 和 How to handle ‘undefined’ in javascript
那个“重复”是关于对象属性的,所以有些答案不太适用于这个问题,询问变量。
【参考方案1】:
如果您有兴趣了解变量是否已声明而不管其值如何,那么使用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')
与undefined
的直接比较很麻烦,因为undefined
可以被覆盖。
window.undefined = "foo";
"foo" == undefined // true
正如@CMS 所指出的,这已在 ECMAScript 第 5 版中进行了修补,并且undefined
是不可写的。
if (window.myVar)
也会包含这些虚假值,所以它不是很健壮:
感谢@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,如果myVariable
未声明...,第三种情况将抛出ReferenceError
@Anurag,不客气,既然你谈到了 ES5,也许值得一提的是,undefined
现在被描述为不可写、不可配置和不可枚举。所以,window.undefined = "omg";
只会静默失败或进入严格模式。
“typeof”可以重新定义吗?
typeof 是一种语言语句,它不能被重新定义,就像 if/else/while/for/function 等一样。
undefined
在现代浏览器中是不可变的。设置 window.undefined
没有任何作用。【参考方案2】:
我个人使用
myVar === undefined
警告:请注意,===
用于 ==
,并且 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
)工作得很好。如果你真的在乎,你可以自己阅读有关此主题的内容。)
【讨论】:
undefined
被重新定义的可能性稍大一些,因为人们确实将它用于此类检查。有些人在进行此类检查时习惯性地将常量放在左侧:if (undefined == someVariable)
。只需要一个错字就可以默默地重新定义undefined
:if (undefined = someVariable)
。
我从不在 LHS 上编写具有 undefined
的代码。即使我这样做了,我使用===
而不是==
的事实也使得错字极不可能出现。但==
不正确的事实更令人担忧。无论如何,这样的错误通常很容易找到。有点像这个错误:typeof x == "undefned"
.
这怎么可能被投票 41 次,它根本行不通。如果myVar
确实是未定义的,代码会抛出一个错误,而且很容易测试——jsfiddle.net/WcM5g正确的方法是typeof myVar === 'undefined'
。
@Laurent:开个玩笑吧?这假设变量以某种方式声明,例如通过var
关键字或函数参数。在我(故意)编写尝试以任何方式对未声明的变量进行操作的代码之前,我会出卖自己的灵魂。请记住,未声明和未定义是 JS 中的两个不同概念。
@Andy 在 C(和 C++)中,像这样反转操作数是常见且良好的做法,以避免拼写错误。 if (NULL = myVar)
无法编译并立即被捕获,而 if (myVar = NULL)
创建的错误可能难以追踪,具体取决于它周围的其他代码。现代编译器应该给你一个警告,但是许多有经验的 C 程序员已经养成了交换顺序的习惯。【参考方案3】:
2020 年更新
我更喜欢 typeof
检查的原因之一(即 undefined
可以重新定义)与 ECMAScript 5 的大规模采用无关。另一个,您可以使用 typeof
检查类型一个未声明的变量,总是小众。因此,我现在建议在大多数情况下使用直接比较:
myVariable === undefined
2010 年的原始答案
使用typeof
是我的偏好。当变量从未被声明时,它将起作用,这与与==
或===
运算符的任何比较或使用if
的类型强制不同。 (undefined
与 null
不同,也可能在 ECMAScript 3 环境中重新定义,这使得比较不可靠,尽管现在几乎所有常见的环境都符合 ECMAScript 5 或更高版本)。
if (typeof someUndeclaredVariable == "undefined")
// Works
if (someUndeclaredVariable === undefined)
// Throws an error
【讨论】:
您可能想检查是否已经定义了代表某项功能的特定全局变量。例如,库代码可能希望检查该库以前是否未被包含。 'xyz' in window 或 'xyz' in self 更好 @JamiePate:为了清楚起见,我不同意'xyz' in window
是比typeof xyz == "undefined"
更好的答案,因为它正在测试错误的东西。 in
运算符检查属性是否存在,而不管其值如何,而问题至少似乎是在询问如何测试变量的值是否为undefined
。也许我可以选择一个更好的例子是var foo; "foo" in window
;这返回 true 而 foo
肯定是未定义的。
@JamiePate:为什么xyz === undefined
比typeof xyz == "undefined"
好?同意全局变量,但我们两个中只有你一直建议检查 window
的属性。
在大多数情况下它是多余的(而且可读性较差)。如果你知道 xyz 是一个声明的变量,为什么还要经历额外的麻烦呢?在某些浏览器中类型检查和字符串比较要慢得多,所以如果你在一个紧密的循环中做很多事情,你会失去一些性能。 jsperf.com/type-of-undefined-vs-undefined/6【参考方案4】:
你可以使用typeof
,像这样:
if (typeof something != "undefined")
// ...
【讨论】:
或者只是something !== undefined
,假设你已经完成了var undefined
,谨慎行事。
很高兴看到您现在添加了引号。但是,正如my answer 中所述,请注意,在这种情况下不需要严格比较(!==
),因为typeof
将始终返回一个字符串。
Mathias:这里使用严格或非严格比较是个人喜好问题。两者都将始终有效,而且都不是更正确的。这可能取决于您的默认位置是始终使用严格比较,除非特别需要类型强制(例如 Crockford 推荐的),或者您是否更喜欢使用非严格比较,除非需要严格。
这是不准确的。你绝对不需要需要使用typeof
。
哦,现在我明白你的意思了;您的评论具有误导性,因为看起来与代码的正确性有关。是的,一个人不需要使用它,因为一切都取决于品味; 如果你知道自己在做什么,你甚至不需要清理用户输入;这并不意味着它不应该完成。在这种情况下,在所有答案中,使用typeof
是最安全且不易出错的选项。除了写这样令人困惑的评论之外,我还会编辑答案以使用另一个术语而不是 need。比如“你可以|应该|更好|可以使用typeof
” :)【参考方案5】:
2018 年 7 月 25 日更新
这篇文章第一次发表已经将近五年了,JavaScript 已经走过了漫长的道路。在重复原始帖子中的测试时,我发现以下测试方法之间没有一致的区别:
abc === undefined
abc === void 0
typeof abc == 'undefined'
typeof abc === 'undefined'
即使我修改了测试以防止 Chrome 优化它们,但差异并不显着。因此,为了清楚起见,我现在推荐abc === undefined
。
来自chrome://version
的相关内容:
原帖 2013-11-01
在 Google Chrome 中,以下测试比 typeof
测试要快一些:
if (abc === void 0)
// Undefined
差异可以忽略不计。但是,对于知道void 0
含义的人来说,这段代码更简洁明了。但是请注意,abc
仍必须声明。
typeof
和 void
都明显快于直接与 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
请注意,第一行以 milli 秒为单位,而第二行以 nano 秒为单位。 3.4 纳秒的差异不算什么。在随后的测试中,时间非常一致。
【讨论】:
哇,这是-1,太令人心碎了;我花了很多时间来测试这个。那好吧。这是很好的信息,所以我会把它留在这里。请记住,不要使用===
来测试undefined
!
我认为 -1 是因为 1) 对于知道 void 0 意味着什么的人来说一目了然,因为
void 0
对我来说听起来更不寻常,2 ) 你应该 share your perf tests 代替,但主要是 3) 如果 abc
未定义,你的第一个示例 (abc === void 0
) 会引发异常。
将你的方法添加到我的测试列表中并且它确实检查了(不是我怀疑你)--jsfiddle.net/drzaus/UVjM4/8
我认为考虑到这些数字(来自不久前的数据),清晰度和速度之间的最佳折衷方案是 typeof
测试。
我发现 undefined 比较比 void 0 慢,这很令人惊讶。我想运行的 JS 版本足够新,可以保证 undefined 保持不变。好伤心。【参考方案6】:
如果它是未定义的,它将不等于包含字符“未定义”的字符串,因为该字符串不是未定义的。
你可以检查变量的类型:
if (typeof(something) != "undefined") ...
有时您甚至不必检查类型。如果变量的值在设置时不能评估为 false(例如,如果它是一个函数),那么您可以只评估变量。示例:
if (something)
something(param);
【讨论】:
不需要括号:typeof
是一个运算符,而不是一个函数。
@Tim - 可以双向使用。
@Tim:@Nick 是正确的。见developer.mozilla.org/en/Core_Javascript_1.5_Reference/…
是的,我知道它与括号一起工作,这是因为这里的括号形成了分组运算符,它简单地计算并返回内部的操作数。我只是说它们是不必要的。【参考方案7】:
if (typeof foo == 'undefined')
// Do something
;
请注意,在这种情况下,不需要严格比较 (!==
),因为typeof
将始终返回一个字符串。
【讨论】:
分号 (;
) 是怎么回事?
@J-P:右大括号后的分号只是一个空语句。
@Gumbo,抱歉,我想问的是:“分号的作用是什么?”
我没有遇到过没有if()
就无法处理if()
的缩小器...您指的是哪些缩小器?你说这就是你结束所有其他陈述的方式......我想这是真的。但是,块语句
已经是它自己的语句。从技术上讲,添加;
使其成为两个语句。从语法上讲,它是多余的。即使是自动分号插入也不会在那里添加分号......
@J-P:我想我是在多年前阅读the Packer documentation 后开始这样做的。 Packer 需要在 function()
声明之后使用分号。不过你是对的——显然在if
声明之后不需要它,但不知何故我仍然认为它是有道理的。【参考方案8】:
说明各种答案结果的一些场景: http://jsfiddle.net/drzaus/UVjM4/
(请注意,in
测试使用 var
在作用域包装器中会有所不同)
参考代码:
(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
【讨论】:
注意undefined
在作用域包装器中的使用;这不仅可以防止“哦,但是undefined
可以重新定义”的(不寻常的)情况,而且还可以“帮助”缩小。【参考方案9】:
在this article 我读到像Underscore.js 这样的框架使用这个函数:
function isUndefined(obj)
return obj === void 0;
【讨论】:
【参考方案10】:就个人而言,我总是使用以下内容:
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() 的一个原因是,如果尚未定义变量,它不会引发错误。
我更喜欢有使用的方法
x === undefined
因为如果 x 之前没有声明过,它会失败并在我的脸上爆炸,而不是默默地通过/失败。这提醒我 x 未声明。我认为 JavaScript 中使用的所有变量都应该声明。
【讨论】:
你可以使用作用域包装器重新声明undefined
:(function($, undefined) /* undefined is 'abc' in here */ )(jQuery, 'abc');
,这就是为什么人们抱怨它在技术上不安全,除非你 100% 确定你知道你的代码在哪里运行。跨度>
关于希望未声明的变量爆炸的要点 - typeof 不会发生这种情况。
使用 2021 年 7 月版 Chrome for Windows(版本 92.0.4515.107),我尝试了: if ( myVar === undefined ), if ( myVar === 'undefined' ), if ( myVar == = void 0),或者 if ( !myVar ) 全部失败!每个案例都抛出了一个未定义的 JavaScript 错误,并有效地返回了一个“真”,导致分支被采用……解决方案:if (!window.myVar) myVar = false;这就是我所需要的,如果没有包含以前的库以将其初始化为 0/false,则将其全局声明为 false。所以仅供参考,最好的解决方案是使用 window 对象!【参考方案11】:
我知道检查undefined
的最可靠方法是使用void 0
。
这与新旧浏览器兼容,并且在某些情况下不能像window.undefined
那样被覆盖。
if( myVar === void 0)
//yup it's undefined
【讨论】:
这是被低估的,恕我直言,这是检查未定义内容的更好方法。 绝对正确,但我想如果undefined !== void 0
,您可能在所述代码库中存在其他严重问题。
并且当 myVar
之前没有被声明过时,它会暴露抛出错误。【参考方案12】:
由于其他答案都没有帮助我,我建议这样做。它在 Internet Explorer 8 中对我有用:
if (typeof variable_name.value === 'undefined')
// variable_name is undefined
【讨论】:
【参考方案13】:// x has not been defined before
if (typeof x === 'undefined') // Evaluates to true without errors.
// These statements execute.
if (x === undefined) // Throws a ReferenceError
【讨论】:
【参考方案14】: 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
【讨论】:
【参考方案15】:与@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.");
【讨论】:
得到这样的myVar is not defined
错误将是一个好的事情,特别是当你专门写“如果我忘记声明”[强调矿]。当我在代码运行之前遇到错误时,我喜欢它。如果您想了解我对您的回答的更多看法,我已经在我的回答下制作了相关的 cmets。【参考方案16】:
我将它用作函数参数并在函数执行时将其排除在外,这样我就得到了“真正的”未定义。尽管它确实需要您将代码放入函数中。我在阅读 jQuery 源代码时发现了这一点。
undefined = 2;
(function (undefined)
console.log(undefined); // prints out undefined
// and for comparison:
if (undeclaredvar === undefined) console.log("it works!")
)()
当然你也可以使用typeof
。但是我所有的代码通常都在一个包含函数中,所以使用这种方法可能会在这里和那里节省一些字节。
【讨论】:
如果 var undeclaredvar 确实未声明,它会给出 ReferenceError。这是属性 - 然后它可以工作,例如:var undeclaredvar = window.someUndeclaredVar; if (undeclaredvar === undefined) console.log("it works!").
请在发布之前测试您的示例。以上是关于如何检查 JavaScript 中的“未定义”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在外部 JavaScript 库中定义函数时如何检查未定义? (Angular4/5)
Chrome Inspector 中的 Javascript 调试:变量在手表和控制台中显示为未定义,但可以在悬停时检查