如果我有对象的引用:

var test = {};

可能(但不是立即)具有嵌套对象,例如:

{level1: {level2: {level3: "level3"}}};

检查深度嵌套对象中是否存在属性的最佳方法是什么?

警报(测试级别1);生成未定义,但警告(test.level1.level2.level3);失败。

我目前正在做这样的事情:

if(test.level1 && test.level1.level2 && test.level1.level2.level3) {
    alert(test.level1.level2.level3);
}

但我想知道是否有更好的方法。


当前回答

在代码库(safeRead)中有一个函数,它将以安全的方式执行此操作。。。即

safeRead(test, 'level1', 'level2', 'level3');

如果任何属性为null或未定义,则返回空字符串

其他回答

现在,我们还可以使用reduce循环嵌套键:

//@params o<对象>//@params路径<string>应为“obj.prop1.prop2.prop3”//返回:obj[path]值或“false”(如果prop不存在)const objPropIfExists=o=>路径=>{常量级别=路径.split('.');常量res=(levels.length>0)? level.reduce((a,c)=>a[c]||0,o):o[路径];return(!!res)?res:假}常量对象={name:'名称',sys:{country:“AU”},main:{temp:“34”,temp_min:“13”},能见度:“35%”}const exists=objPropIfExists(obj)('main.temp')const doesntExist=objPropIfExists(obj)('main.temp.foo.baz')console.log(存在,不存在)

我已经使用这个函数来访问深度嵌套对象的财产,它对我来说很有效。。。

这是函数

/**
 * get property of object
 * @param obj object
 * @param path e.g user.name
 */
getProperty(obj, path, defaultValue = '-') {
  const value = path.split('.').reduce((o, p) => o && o[p], obj);

  return value ? value : defaultValue;
}

这是我访问深度嵌套对象属性的方式

{{ getProperty(object, 'passengerDetails.data.driverInfo.currentVehicle.vehicleType') }}

根据之前的评论,这里是另一个无法定义主对象的版本:

// Supposing that our property is at first.second.third.property:
var property = (((typeof first !== 'undefined' ? first : {}).second || {}).third || {}).property;

CMS解决方案工作得很好,但使用/语法可能更方便。我建议如下

var checkNested = function(obj, structure) {

  var args = structure.split(".");

  for (var i = 0; i < args.length; i++) {
    if (!obj || !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

CMS给出的答案也适用于空检查的以下修改

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 == null || !obj.hasOwnProperty(args[i]) ) 
                {
                    return false;
                }
                obj = obj[args[i]];
            }
            return true;
    }