如果我有对象的引用:

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

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


当前回答

getValue (o, key1, key2, key3, key4, key5) {
    try {
      return o[key1][key2][key3][key4][key5]
    } catch (e) {
      return null
    }
}

其他回答

根据@Stephane LaFlèche的回答,我提出了另一个剧本版本。

JSFiddle演示

var obj = {"a":{"b":{"c":"Hello World"}},"resTest":"potato","success":"This path exists"};
checkForPathInObject = function(object,path,value) {
        var pathParts   = path.split("."),
            result      = false;
        // Check if required parameters are set; if not, return false
        if(!object || typeof object == 'undefined' || !path || typeof path != 'string')
            return false;
        /* Loop through object keys to find a way to the path or check for value
         * If the property does not exist, set result to false
         * If the property is an object, update @object
         * Otherwise, update result */
        for(var i=0;i<pathParts.length;i++){
            var currentPathPart = pathParts[i];
            if(!object.hasOwnProperty( currentPathPart )) {
                result = false;
            } else if (object[ currentPathPart ] && path == pathParts[i]) {
                result = pathParts[i];
                break;
            } else if(typeof object[ currentPathPart ] == 'object') {
                object = object[ currentPathPart ];
            } else {
                result = object[ currentPathPart ];
            }
        }
        /* */
        if(typeof value != 'undefined' && value == result)
            return true;
        return result;
};
// Uncomment the lines below to test the script
// alert( checkForPathInObject(obj,'a.b.c') ); // Results "Hello World"
// alert( checkForPathInObject(obj,'a.success') ); // Returns false
// alert( checkForPathInObject(obj,'resTest', 'potato') ); // Returns true

您可以使用“.”分隔对象和路径

函数checkPathExist(obj,路径){var pathArray=路径.split(“.”)for(pathArray的var i){if(反射get(obj,i)){obj=obj[i];}其他{return false;}}返回true;}var测试={level1:{level2:{level3:‘level3‘}}}};console.log('level.level.level3=>',checkPathExist(测试,'level.level 2.level3'));//真的console.log('level.level.foo=>',checkPathExist(测试,'level.level 2.foo'));//假的

另一个ES5解决方案:

function hasProperties(object, properties) {
    return !properties.some(function(property){
        if (!object.hasOwnProperty(property)) {
            return true;
        }
        object = object[property];
        return false;
    });
}

基于这个答案,我使用ES2015提出了一个通用函数,可以解决这个问题

function validChain( object, ...keys ) {
    return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}

var test = {
  first: {
    second: {
        third: "This is not the key your are looking for"
    }
  }
}

if ( validChain( test, "first", "second", "third" ) ) {
    console.log( test.first.second.third );
}

我创建了一个小函数来安全地获取嵌套对象财产。

function getValue(object, path, fallback, fallbackOnFalsy) {
    if (!object || !path) {
        return fallback;
    }

    // Reduces object properties to the deepest property in the path argument.
    return path.split('.').reduce((object, property) => {
       if (object && typeof object !== 'string' && object.hasOwnProperty(property)) {
            // The property is found but it may be falsy.
            // If fallback is active for falsy values, the fallback is returned, otherwise the property value.
            return !object[property] && fallbackOnFalsy ? fallback : object[property];
        } else {
            // Returns the fallback if current chain link does not exist or it does not contain the property.
            return fallback;
        }
    }, object);
}

或者更简单但稍微不可读的版本:

function getValue(o, path, fb, fbFalsy) {
   if(!o || !path) return fb;
   return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? !o[p] && fbFalsy ? fb : o[p] : fb, o);
}

或者更短,但没有错误标志:

function getValue(o, path, fb) {
   if(!o || !path) return fb;
   return path.split('.').reduce((o, p) => o && typeof o !== 'string' && o.hasOwnProperty(p) ? o[p] : fb, o);
}

我测试了:

const obj = {
    c: {
        a: 2,
        b: {
            c: [1, 2, 3, {a: 15, b: 10}, 15]
        },
        c: undefined,
        d: null
    },
    d: ''
}

下面是一些测试:

// null
console.log(getValue(obj, 'c.d', 'fallback'));

// array
console.log(getValue(obj, 'c.b.c', 'fallback'));

// array index 2
console.log(getValue(obj, 'c.b.c.2', 'fallback'));

// no index => fallback
console.log(getValue(obj, 'c.b.c.10', 'fallback'));

要查看所有包含文档和测试的代码,您可以查看我的github要点:https://gist.github.com/vsambor/3df9ad75ff3de489bbcb7b8c60beebf4#file-javascriptgetnestedvalues js