检查JavaScript中的对象属性是否未定义的最佳方法是什么?
检查JavaScript中的对象属性是否未定义的最佳方法是什么?
使用:
if (typeof something === "undefined") {
alert("something is undefined");
}
如果具有某些属性的对象变量可以使用如下所示的相同内容:
if (typeof my_obj.someproperties === "undefined"){
console.log('the property is not available...'); // print into console
}
自ECMAScript 5以来, undefined
不能被覆盖,所以 my_obj === undefined
也会工作,但只有 my_obj
存在。这可能是也可能不是,因为你也可以使用 null
如果你需要这种语义(见 JavaScript中的null和undefined有什么区别?)。但是对于对象属性,无论属性是否存在,它都可以工作。
使用:
if (typeof something === "undefined") {
alert("something is undefined");
}
如果具有某些属性的对象变量可以使用如下所示的相同内容:
if (typeof my_obj.someproperties === "undefined"){
console.log('the property is not available...'); // print into console
}
自ECMAScript 5以来, undefined
不能被覆盖,所以 my_obj === undefined
也会工作,但只有 my_obj
存在。这可能是也可能不是,因为你也可以使用 null
如果你需要这种语义(见 JavaScript中的null和undefined有什么区别?)。但是对于对象属性,无论属性是否存在,它都可以工作。
我相信这个话题有很多不正确的答案。与普遍看法相反,“未定义”是 不 JavaScript中的关键字,实际上可以为其分配值。
执行此测试的最强大方法是:
if (typeof myVar === "undefined")
这将始终返回正确的结果,甚至处理其中的情况 myVar
没有宣布。
var undefined = false; // Shockingly, this is completely legal!
if (myVar === undefined) {
alert("You have been misled. Run away!");
}
另外, myVar === undefined
会在myVar未声明的情况下引发错误。
在JavaScript中有 空值 并且有 未定义。它们有不同的含义。
Marijn Haverbeke在他的免费在线书中说:雄辩的JavaScript“(强调我的):
还有一个类似的值null,其含义是“此值已定义,但它没有值”。 undefined和null之间的意义差异主要是学术性的,通常不是很有趣。 在实际程序中,通常需要检查某些东西是否“有价值”。在这些情况下,可以使用表达式== undefined,因为即使它们不是完全相同的值,null == undefined也会产生true。
所以,我想检查某些内容是否未定义的最佳方法是:
if (something == undefined)
希望这可以帮助!
编辑: 为了响应您的编辑,对象属性应该以相同的方式工作。
var person = {
name: "John",
age: 28,
sex: "male"
};
alert(person.name); // "John"
alert(person.fakeVariable); // undefined
尽管在这里被许多其他答案强烈推荐, typeof
是一个糟糕的选择。它永远不应该用于检查变量是否具有该值 undefined
,因为它作为值的组合检查 undefined
以及变量是否存在。在绝大多数情况下,您知道变量何时存在,以及 typeof
如果您在变量名称或字符串文字中输入拼写错误,则会引入静默失败的可能性 'undefined'
。
var snapshot = …;
if (typeof snaposhot === 'undefined') {
// ^
// misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;
if (typeof foo === 'undefned') {
// ^
// misspelled – this will never run, but it won’t throw an error!
}
因此,除非您正在进行特征检测²,否则给定名称是否在范围内(如检查)是不确定的 typeof module !== 'undefined'
作为特定于CommonJS环境的代码中的一步), typeof
在变量上使用时是一个有害的选择,正确的选择是直接比较值:
var foo = …;
if (foo === undefined) {
⋮
}
一些常见的误解包括:
读取“未初始化”变量(var foo
)或参数(function bar(foo) { … }
,称为 bar()
) 将失败。这根本不是真的 - 没有显式初始化的变量和没有给定值的参数总是变成 undefined
,并且始终在范围内。
那 undefined
可以被覆盖。这还有很多。 undefined
不是JavaScript中的关键字。相反,它是具有Undefined值的全局对象上的属性。但是,自从ES5以来,这个属性已经存在 只读 和 非可配置。没有现代浏览器允许 undefined
物业需要更改,截至2017年,这种情况已经存在很长时间了。缺乏严格模式不会影响 undefined
的行为要么 - 它只是做出陈述 undefined = 5
什么也不做,而不是扔。但是,由于它不是关键字,您可以 宣布 名称变量 undefined
,这些变量可以改变,使这个曾经常见的模式:
(function (undefined) {
// …
})()
更多 比使用全局更危险 undefined
。如果必须与ES3兼容,请更换 undefined
同 void 0
- 不要诉诸 typeof
。 (void
一直是一元运算符,它计算任何操作数的Undefined值。)
通过变量如何解决问题,是时候解决实际问题了:对象属性。没有理由使用 typeof
对于对象属性。有关特征检测的早期例外不适用于此处 - typeof
只对变量有特殊行为,引用对象属性的表达式不是变量。
这个:
if (typeof foo.bar === 'undefined') {
⋮
}
是 总是完全相同 到这个³:
if (foo.bar === undefined) {
⋮
}
并考虑到上述建议,以避免让读者对您使用的原因感到困惑 typeof
,因为它最有意义 ===
检查是否相等,因为它可以重构为稍后检查变量的值,因为它只是看起来更好, 你应该经常使用 === undefined
³这里也是。
在涉及对象属性时需要考虑的其他事项是您是否真的想要检查 undefined
一点都不对象上可以不存在给定的属性名称(生成值) undefined
当读取时),使用值呈现在对象本身上 undefined
,使用值呈现在对象的原型上 undefined
,或出现在任何非undefined
值。 'key' in obj
会告诉你一个键是否在对象原型链的任何地方,并且 Object.prototype.hasOwnProperty.call(obj, 'key')
会告诉你它是否直接在物体上。我不会在这个关于原型和使用对象作为字符串键映射的答案中详细说明,因为它主要是为了对抗其他答案中的所有不良建议,而不管原始问题的可能解释如何。阅读 MDN上的对象原型 更多!
¹异常选择示例变量名称?这是来自Firefox的NoScript扩展的真正死代码。
²不要以为不知道一般情况下不知道范围是什么。滥用动态范围造成的奖金漏洞: Project Zero 1225
³再次假设一个ES5 +环境 undefined
是指 undefined
全局对象的属性。替代 void 0
除此以外。
这是什么意思: “未定义的对象属性”?
实际上它可能意味着两件完全不同的东西!首先,它可以意味着 从未定义过的属性 在对象中,第二,它可以意味着 具有未定义值的属性。我们来看看这段代码:
var o = { a: undefined }
是 o.a
未定义?是!它的价值是不确定的。是 o.b
未定义?当然!根本没有属性'b'!好的,现在看看两种情况下不同方法的表现如何:
typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false
我们可以清楚地看到 typeof obj.prop == 'undefined'
和 obj.prop === undefined
是等价的,他们不区分那些不同的情况。和 'prop' in obj
可以检测到根本没有定义属性的情况,并且不会注意可能未定义的属性值。
1)您想知道属性是否由第一个或第二个含义(最典型的情况)定义。
obj.prop === undefined // IMHO, see "final fight" below
2)您只想知道对象是否具有某些属性而不关心其值。
'prop' in obj
x.a === undefined
或这个 typeof x.a == 'undefined'
加薪 ReferenceError: x is not defined
如果没有定义x。undefined
是一个全局变量(实际上它是 window.undefined
在浏览器中)。它自ECMAScript第1版以来一直受到支持,自ECMAScript 5以来一直受到支持 只读。所以在现代浏览器中它不可能 重新定义为真 正如许多作者喜欢吓唬我们一样,但对于旧浏览器来说,这仍然是正确的。obj.prop === undefined
VS typeof obj.prop == 'undefined'
优点 obj.prop === undefined
:
undefined
弊端 obj.prop === undefined
:
undefined
可以在旧浏览器中覆盖优点 typeof obj.prop == 'undefined'
:
弊端 typeof obj.prop == 'undefined'
:
'undefned'
(拼写错误)这里只是一个字符串常量,所以如果你像我刚才那样拼错了它,JavaScript引擎就无法帮助你。Node.js支持全局变量 undefined
如 global.undefined
(它也可以在没有'全局'前缀的情况下使用)。我不知道服务器端JavaScript的其他实现。
问题可归结为三种情况:
undefined
。undefined
。这告诉我们一些我认为重要的事情:
未定义的成员与具有未定义值的已定义成员之间存在差异。
但不幸的是 typeof obj.foo
我们没有告诉我们这三种情况中的哪一种。但是我们可以将它与之结合起来 "foo" in obj
区分案件。
| typeof obj.x === 'undefined' | !("x" in obj)
1. { x:1 } | false | false
2. { x : (function(){})() } | true | false
3. {} | true | true
值得注意的是,这些测试是相同的 null
条目也是
| typeof obj.x === 'undefined' | !("x" in obj)
{ x:null } | false | false
我认为在某些情况下更有意义(并且更清楚)检查属性是否存在,而不是检查它是否未定义,并且唯一的情况是这种检查将是不同的是案例2,这是罕见的情况具有未定义值的对象中的实际条目。
例如:我刚刚重构了一堆代码,这些代码检查对象是否具有给定属性。
if( typeof blob.x != 'undefined' ) { fn(blob.x); }
在没有检查未定义的情况下编写时更清楚。
if( "x" in blob ) { fn(blob.x); }
但正如已经提到的,这些并不完全相同(但对我的需求来说已经足够好了)。
if ( typeof( something ) == "undefined")
这对我有用,而其他人没有。
我不确定使用的来源 ===
同 typeof
来自,并且作为一种惯例,我看到它在许多库中使用,但是typeof运算符返回一个字符串文字,我们知道这个,所以为什么你也要打字检查呢?
typeof x; // some string literal "string", "object", "undefined"
if (typeof x === "string") { // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") { // sufficient
交叉我的 回答 来自相关问题 如何在JavaScript中检查“undefined”?
具体到这个问题,请参阅测试用例 someObject.<whatever>
。
一些场景说明了各种答案的结果: 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
如果你这样做
if (myvar == undefined )
{
alert('var does not exists or is not initialized');
}
变量时它会失败 myvar
不存在,因为未定义myvar,因此脚本被破坏且测试无效。
由于窗口对象在函数外部具有全局范围(默认对象),因此声明将“附加”到窗口对象。
例如:
var myvar = 'test';
全局变量 MYVAR 是相同的 window.myvar 要么 窗口[ 'MYVAR']
为避免在存在全局变量时测试错误,最好使用:
if(window.myvar == undefined )
{
alert('var does not exists or is not initialized');
}
变量确实存在的问题无关紧要,其值不正确。否则,使用undefined初始化变量是愚蠢的,最好使用值false来初始化。当您知道所声明的所有变量都使用false初始化时,您只需检查其类型或依赖 !window.myvar
检查它是否具有正确/有效的值。所以即使没有定义变量那么 !window.myvar
是一样的 myvar = undefined
要么 myvar = false
要么 myvar = 0
。
当您需要特定类型时,请测试变量的类型。为了加快测试条件,您最好:
if( !window.myvar || typeof window.myvar != 'string' )
{
alert('var does not exists or is not type of string');
}
当第一个和简单条件为真时,解释器会跳过下一个测试。
最好使用变量的实例/对象来检查它是否具有有效值。它更稳定,是一种更好的编程方式。
(y)的