JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]

Posted

技术标签:

【中文标题】JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]【英文标题】:JavaScript, elegant way to check nested object properties for null/undefined [duplicate]JavaScript,检查嵌套对象属性是否为空/未定义的优雅方法[重复] 【发布时间】:2014-07-11 14:45:41 【问题描述】:

我不时遇到的一个“问题”是我有一个对象,例如user = 并在使用该应用程序的过程中填充。假设在某个地方,在 AJAX 调用或我这样做之后:

user.loc = 
    lat: 50,
    long: 9

在另一个地方我想检查user.loc.lat 是否存在。

if (user.loc.lat) 
    // do something

如果它不存在,这将导致错误。如果user.loc.latundefineduser.loc 当然也是undefined

"Cannot read property 'lat' of null" - Dev Tools error

这意味着我需要像这样检查它:

if (user.loc) 
    if (user.loc.lat) 
        // do something
    

if (user.loc && user.loc.lat) 
    // do something

这不是很漂亮,而且我的对象越大,效果就越差 - 显然(想象一下 10 层嵌套)。 如果user.loc 也是undefinedif(user.loc.lat) 不只是返回 false,这让我感到很沮丧。

检查这种情况的理想方法是什么?

【问题讨论】:

试试这个if(user && user.loc && user.loc.lat) 您可以使用typeof检查 null 和 undefined 的值 @AamirAfridi——尽管 OP 是这样写的,但测试应该停止在最后一个对象,而不是属性。例如如果user.loc.lat 存在但具有错误值(例如0),则测试将返回错误。 :-) 【参考方案1】:

您可以使用惰性and 组合检查:

if(user.loc && user.loc.lat)  ...

或者,您使用 CoffeeScript。并且 ES2020 有新的语法( Nullish coalescing Operator )。

user.loc?.lat?. '...'

它将检查loc 属性并防止空对象。

【讨论】:

对不起,你们都回答得很快。您的第一种方法也是我想避免的情况。考虑到我有 5 到 15 层嵌套的巨大对象。 这里没有太多选择。 (1) 手动或使用 CoffeeScript 进行属性检查,(2) try/catch。如果您有一个具有 15 级嵌套的对象,并且它的属性可能在任何级别都不存在,那么我认为您的应用程序有一些次优设计模式。 这是一个例子。我想要一种方法来涵盖这种情况。我显然会避免 15 层嵌套,但如果一个旧的服务器端应用程序就是这样做的,我必须处理它怎么办?这就是为什么我想涵盖那个场景 .? 被称为optional chaining operator。空值合并运算符` (??) 与 OR 运算符 (||) 非常不同且更相似。 developer.mozilla.org/en-US/docs/Web/javascript/Reference/….【参考方案2】:

试试这个if(user && user.loc && user.loc.lat) ...

您可以使用typeof检查 null 和 undefined 的值

如果.loc 的值是false,则可以尝试

if(user && user.loc && typeof(user.loc)!=="undefined")...

如果您有一个巨大的嵌套对象,请查看

Source.

function checkNested(obj /*, level1, level2, ... levelN*/) 
  var args = Array.prototype.slice.call(arguments),
      obj = args.shift();

  for (var i = 0; i < args.length; i++) 
    if (!obj.hasOwnProperty(args[i])) 
      return false;
    
    obj = obj[args[i]];
  
  return true;


var test = level1:level2:level3:'level3' ;

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false

更新: 试试lodash.get

【讨论】:

对不起,你们都回答得很快。这也是我想避免的情况。考虑到我有 5 到 15 层嵌套的巨大对象。 我讨厌人们不加评论就拒绝投票。【参考方案3】:

你可以使用这样的实用函数:

get = function(obj, key) 
    return key.split(".").reduce(function(o, x) 
        return (typeof o == "undefined" || o === null) ? o : o[x];
    , obj);

用法:

 get(user, 'loc.lat')     // 50
 get(user, 'loc.foo.bar') // undefined

或者,仅检查属性是否存在,而不获取其值:

has = function(obj, key) 
    return key.split(".").every(function(x) 
        if(typeof obj != "object" || obj === null || ! x in obj)
            return false;
        obj = obj[x];
        return true;
    );


if(has(user, 'loc.lat')) ...

【讨论】:

爱它!很好的解决方案。 get 方法的问题是它可能从链中的任何地方返回一个属性,它没有专门测试最后一个属性。 @RobG 怎么样?一旦它遇到一个未定义的,它就会一直通过并且结果是未定义的。 我希望 lodash 能和这个函数。_.has 是最接近的,但不检查值。 实际上,从头开始,确实如此!只需使用_.get***.com/a/24046380/654708【参考方案4】:

好吧,javascript 有 try-catch。根据您实际需要做的事情(即,如果它是 undefined,您的 else 语句会是什么样子),这可能就是您想要的。

示例:

try 
   user.loc.lat.doSomething();
 catch(error) 
   //report

【讨论】:

啊当然。也是一个很好的答案,谢谢! 我认为抛出异常而不是 if-else 不是一个好主意,如果您知道 var 可能未设置,我不认为这是一个异常,因此您应该处理它没有尝试捕获。 (当然你可以加入 else 子句)然后。 我喜欢这个解决方案,用于处理有时会因条件句而变得难以阅读的简单内容。 @JonasStensved 指出不使用 try catch 是因为启动异常(我认为,在您编写 throw 之前,您不会启动它)但问题可能是块中出现其他问题,您将无法检测到它关于未来。 @pikilon 经验法则:不要使用异常进行流量控制。在您的情况下,某些事情确实出乎意料并且是异常,然后抛出。否则将其作为任何其他代码条件处理。

以上是关于JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

检查 JavaScript 中是不是存在深度嵌套对象属性的最简单方法是啥? [复制]

JavaScript - 编辑嵌套对象

测试嵌套 JavaScript 对象键是不是存在

测试嵌套 JavaScript 对象键是不是存在

如何检查对象内的数组是不是为空 JavaScript

检查对象中的值是不是为空或空javascript