如何检查可能未定义的对象上是否存在属性?

24

有一些关于如何检查对象属性是否存在的问题在S.O.上得到了解答。示例答案是使用Object.prototype.hasOwnProperty()

然而,如果要检查潜在未定义对象的属性,该怎么办?

如果试图直接检查未定义对象上的属性是否存在,则会出现引用错误。

从语义上讲,似乎最好直接检查代码if (obj.prop) //dosomething——这显示了更清晰的意图。有没有办法实现这个呢?最好,是否有内置的Javascript方法或约定可以做到这一点?

动机:一个包添加了属性user.session.email——但我正在检查电子邮件是否存在,而不是会话,尽管会话可能不存在。

更新: 很多答案都建议使用&&运算符进行短路。我知道这是一种可能的解决方案,但它并不完全符合要求,因为它似乎是在绕过JS对象语法——也就是说,虽然你想真正检查对象上的属性,但你被迫检查对象是否存在才能这样做。

注意:已标记为关闭 为什么要将其标记为关闭?假设这是一个重复的链接可能不会得到相同的答案。我们正在寻找更好、更语义化的解决方案,而将其关闭则意味着“嵌套”等于“可能未定义”。

这个问题有争议:自从最近有一个提案被提出进入阶段1here,可以解决这个问题。同样,这个问题希望有一个更语义化的解决方案,就像提案中所示。


3
这并不是语法错误,而是引用错误。你可以检查 obj && obj.prop - Sebastian Simon
2
obj变量肯定会存在,但可能具有undefined值吗?顺便说一下,测试if (obj.prop)并不测试属性是否存在,它测试的是属性是否存在具有真值。 - nnnnnn
啊 - 问题描述已经修正,但问题仍然有效,因为您实际上是在检查对象和属性是否都存在,而我只想检查属性是否存在。 - steviesh
1
防御式编程的一部分是考虑会引发错误的情况。如果对象可能不存在,则在引用其属性之前,您需要确保它存在。 - Jecoms
@nnnnnn 承认,我之前没有看到过这个链接,我认为它与问题有些关联,并且可以增加问题的内容 - 但答案并不相同。也许我可以在问题中添加细节,明确我正在寻找JS约定或编写更清晰代码的内置方法。 - steviesh
显示剩余6条评论
3个回答

20

如果您确定父对象存在,则:

if(obj && obj.key) {
  console.log(obj.key);
}

然而,如果obj不存在,这个例子将会彻底失败。

if (obj && obj.key) {
  console.log(obj.key);
}

...这就是为什么在检查属性时,您可能希望检查对象是否已定义。这可以确保如果满足条件但属性的对象尚未设置,您不会遇到运行时错误。

if(typeof obj != "undefined" && obj.key) { 
  console.log('you will not see this logged')
}

你会注意到上面的示例没有抛出异常。

var obj = {key: 1};

if(typeof obj != "undefined" && obj.key) {
  console.log('we have obj! and val is : ' + obj.key)
}

这是一种更为保守的方法,但也允许可移植性。如果您想将自己的逻辑分解到一个模块中以供重复使用,您可能还想检查对象是否存在,否则可能会出现您并不关心的应用程序区域中的错误


如果没有更清晰的方法来检查该属性,我将接受这个答案(由其他人提交)。 - steviesh
2
请注意,如果在typeof检查之后,使用letconst定义了变量obj,则typeof obj !=“undefined”将导致引用错误。 - nnnnnn
8
请注意,var a = {a:false, b:0, c:null}破坏了这些测试,因为a.aa.ba.c都不被视为真值,所以if (a && a.a) { ... }不会认为它已定义,但实际上它是定义了的。 - artfulrobot

13

如果你想检查obj和prop是否存在(像你在评论中提到的),你需要这样做:

if(obj && obj.hasOwnProperty('some')) 或者 if(obj && obj.some)

如评论中所述,如果obj未定义,这将抛出错误。更好的比较方法是:

if(typeof obj != "undefined" && obj.hasOwnProperty('some'))

如果 obj 未定义,这将抛出一个异常。 - dgo

-2
你可以这样做:
if(user.session && 'email' in user.session) //do something...

如果您确定用户已定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接