如果我有对象的引用:

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

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


当前回答

ES6答案,经过彻底测试:)

const propExists = (obj, path) => {
    return !!path.split('.').reduce((obj, prop) => {
        return obj && obj[prop] ? obj[prop] : undefined;
    }, obj)
}

→请参阅具有完整测试覆盖范围的Codepen

其他回答

如果像字符串一样处理名称:“t.level1。level2。level3”,则可以在任何深度读取对象属性。

window.t={level1:{level2:{level3: 'level3'}}};

function deeptest(s){
    s= s.split('.')
    var obj= window[s.shift()];
    while(obj && s.length) obj= obj[s.shift()];
    return obj;
}

alert(deeptest('t.level1.level2.level3') || 'Undefined');

如果任何段未定义,则返回undefined。

下面是我的看法-这些解决方案中的大多数都忽略了嵌套数组的情况,如:

    obj = {
        "l1":"something",
        "l2":[{k:0},{k:1}],
        "l3":{
            "subL":"hello"
        }
    }

我可能想检查obj.l2[0].k

使用下面的函数,您可以执行深度测试('l2[0].k',obj)

如果对象存在,函数将返回true,否则返回false

函数deeptest(keyPath,testObj){变量obj;keyPath=keyPath.split('.')var cKey=keyPath.shift();函数get(pObj,pKey){var bracketStart,bracketEnd,o;bracketStart=pKey.indexOf(“[”);if(bracketStart>-1){//检查嵌套数组bracketEnd=pKey.indexOf(“]”);var arrIndex=pKey.substr(bracketStart+1,bracketEnd-bracketStart-1);pKey=pKey.substr(0,括号开始);var n=pObj[pKey];o=n?n[arrIndex]:未定义;}其他{o=pObj[pKey];}返回o;}obj=获取(testObj,cKey);while(obj&&keyPath.length){obj=get(obj,keyPath.shift());}返回typeof(obj)!=='未定义';}变量obj={“l1”:“级别1”,“arr1”:[{“k”:0},{“k”:1},{“k”:2}],“子”:{“a”:“字母a”,“b”:“字母b”}};console.log(“l1:”+深度测试(“l1”,obj));console.log(“arr1[0]:”+深度测试(“arr1[0]”,obj));console.log(“arr1[1].k:”+深度测试(“arr1].k”,obj));console.log(“arr1[1].j:”+深度测试(“arr1].j”,obj));console.log(“arr1[3]:”+深度测试(“arr1[3]”,obj));console.log(“arr2:”+深度测试(“arr2”,obj));

这个问题由来已久。今天,您可以使用可选链接(?.)

let value = test?.level1?.level2?.level3;

资料来源:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

我在寻找属性存在时返回的值,所以我通过上面的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”)//未定义

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