如果我有对象的引用:

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

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


当前回答

function getValue(base, strValue) {

    if(base == null) return;
    
    let currentKey = base;
    
    const keys = strValue.split(".");
    
    let parts;
    
    for(let i=1; i < keys.length; i++) {
        parts = keys[i].split("[");
        if(parts == null || parts[0] == null) return;
        let idx;
        if(parts.length > 1) { // if array
            idx = parseInt(parts[1].split("]")[0]);
            currentKey = currentKey[parts[0]][idx];
        } else {
            currentKey = currentKey[parts[0]];
        }
        if(currentKey == null) return;
    }
    return currentKey;
}

如果结果在嵌套或值本身的任何地方失败,则调用函数返回undefined

const a = {
  b: {
    c: [
      {
        d: 25
      }
    ]
  }
}
console.log(getValue(a, 'a.b.c[1].d'))
// output
25

其他回答

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

还有一个非常紧凑的:

function ifSet(object, path) {
  return path.split('.').reduce((obj, part) => obj && obj[part], object)
}

打电话:

let a = {b:{c:{d:{e:'found!'}}}}
ifSet(a, 'b.c.d.e') == 'found!'
ifSet(a, 'a.a.a.a.a.a') == undefined

它的性能不会很好,因为它拆分了一个字符串(但增加了调用的可读性),并遍历所有内容,即使已经很明显找不到任何内容(但提高了函数本身的可读性。

至少比get快http://jsben.ch/aAtmc

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

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

另一个ES5解决方案:

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

另一个选项(接近这个答案):

function resolve(root, path){
    try {
        return (new Function(
            'root', 'return root.' + path + ';'
        ))(root);
    } catch (e) {}
}

var tree = { level1: [{ key: 'value' }] };
resolve(tree, 'level1[0].key'); // "value"
resolve(tree, 'level1[1].key'); // undefined

更多信息:https://stackoverflow.com/a/18381564/1636522