如果我有对象的引用:

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);
}

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


当前回答

答案很多,但仍然是:为什么不更简单?

获取值的es5版本为:

function value(obj, keys) {
    if (obj === undefined) return obj;
    if (keys.length === 1 && obj.hasOwnProperty(keys[0])) return obj[keys[0]];
    return value(obj[keys.shift()], keys);
}

if (value(test, ['level1', 'level2', 'level3'])) {
  // do something
}

您也可以将其与value(config,['applet',i,'height'])一起使用||42

CMS的ES6解决方案给了我这个想法。

其他回答

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;
    }

另一种解决方法是,例如,使用以下对象:

var x = {
    a: {
        b: 3
    }
};

然后,我所做的是向这个对象添加以下函数:

x.getKey = function(k){
        var r ;
        try {
            r = eval('typeof this.'+k+' !== "undefined"');
        }catch(e){
            r = false;
        }
        if(r !== false){
            return eval('this.'+k);
        }else{
            console.error('Missing key: \''+k+'\'');
            return '';
        }
    };

然后您可以测试:

x.getKey('a.b');

如果未定义,则函数返回“”(空字符串),否则返回现有值。

还请考虑检查链接的另一个更复杂的解决方案:JS对象具有属性深度检查

Object.prototype.hasOwnNestedProperty = function(propertyPath){
    if(!propertyPath)
        return false;

    var properties = propertyPath.split('.');
    var obj = this;

    for (var i = 0; i < properties.length; i++) {
        var prop = properties[i];

        if(!obj || !obj.hasOwnProperty(prop)){
            return false;
        } else {
            obj = obj[prop];
        }
    }

    return true;
};

// Usage: 
var obj = {
   innerObject:{
       deepObject:{
           value:'Here am I'
       }
   }
}

obj.hasOwnNestedProperty('innerObject.deepObject.value');

注:还有一个递归版本。

我在寻找属性存在时返回的值,所以我通过上面的CMS修改了答案。下面是我想到的:

函数getNestedProperty(obj,key){//从键字符串获取属性数组var财产=key.split(“.”);//遍历财产,如果对象为空或属性不存在,则返回未定义的对于(var i=0;i<属性.length;i++){if(!obj||!obj.hasOwnProperty(财产[i])){回来}obj=obj[财产[i]];}//找到嵌套属性,因此返回值返回obj;}用法:getNestedProperty(测试,“level.level2.level3”)//“level3”getNestedProperty(测试,“level.level2.foo”)//未定义

您可以使用递归函数来实现这一点。即使您不知道所有嵌套的对象键名称,也可以使用此方法。

function FetchKeys(obj) {
    let objKeys = [];
    let keyValues = Object.entries(obj);
    for (let i in keyValues) {
        objKeys.push(keyValues[i][0]);
        if (typeof keyValues[i][1] == "object") {
            var keys = FetchKeys(keyValues[i][1])
            objKeys = objKeys.concat(keys);
        }
    }
    return objKeys;
}

let test = { level1: { level2: { level3: "level3" } } };
let keyToCheck = "level2";
let keys = FetchKeys(test); //Will return an array of Keys

if (keys.indexOf(keyToCheck) != -1) {
    //Key Exists logic;
}
else {
    //Key Not Found logic;
}

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

这是函数

/**
 * 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') }}