如果我有对象的引用:

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

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


当前回答

我想我应该再加一个我今天想到的。我对这个解决方案感到自豪的原因是它避免了许多解决方案中使用的嵌套括号,例如Object Wrap(Oliver Steele):

(在本例中,我使用下划线作为占位符变量,但任何变量名称都有效)

//“测试”对象var测试={level1:{level2:{level3:‘level3‘}}}};设_=测试;如果((_=_level1)&&(_=.level2)&&{设level3=_;//做3级的事情}

//您也可以使用“stacked”if语句。如果你的物体很深,这会有帮助。//(除最后一个大括号外,不带嵌套或大括号)设_=测试;如果(_=_.level1)如果(_=_.level2)如果(_=_.level3){设level3=_;//做3级的事情}//或者可以缩进:如果(_=_.level1)如果(_=_.level2)如果(_=_.level3){设level3=_;//做3级的事情}

其他回答

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

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

资料来源:

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

这个功能怎么样?它不需要单独列出每个嵌套属性,而是保持“dot”语法(尽管是字符串),使其更具可读性。如果未找到属性,则返回undefined或指定的默认值,如果找到,则返回属性的值。

val(obj, element, default_value)
    // Recursively checks whether a property of an object exists. Supports multiple-level nested properties separated with '.' characters.
    // obj = the object to test
    // element = (string or array) the name of the element to test for.  To test for a multi-level nested property, separate properties with '.' characters or pass as array)
    // default_value = optional default value to return if the item is not found. Returns undefined if no default_value is specified.
    // Returns the element if it exists, or undefined or optional default_value if not found.
    // Examples: val(obj1, 'prop1.subprop1.subsubprop2');
    // val(obj2, 'p.r.o.p', 'default_value');
    {

        // If no element is being requested, return obj. (ends recursion - exists)
        if (!element || element.length == 0) { return obj; }

        // if the element isn't an object, then it can't have properties. (ends recursion - does not exist)
        if (typeof obj != 'object') { return default_value; }

        // Convert element to array.
        if (typeof element == 'string') { element = element.split('.') };   // Split on dot (.)

        // Recurse into the list of nested properties:
        let first = element.shift();
        return val(obj[first], element, default_value);

    }

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

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

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

我尝试了递归方法:

function objHasKeys(obj, keys) {
  var next = keys.shift();
  return obj[next] && (! keys.length || objHasKeys(obj[next], keys));
}

这个keys.length||退出递归,这样它就不会在没有键可供测试的情况下运行函数。测验:

obj = {
  path: {
    to: {
      the: {
        goodKey: "hello"
      }
    }
  }
}

console.log(objHasKeys(obj, ['path', 'to', 'the', 'goodKey'])); // true
console.log(objHasKeys(obj, ['path', 'to', 'the', 'badKey']));  // undefined

我正在使用它打印一组具有未知键/值的对象的友好html视图,例如:

var biosName = objHasKeys(myObj, 'MachineInfo:BiosInfo:Name'.split(':'))
             ? myObj.MachineInfo.BiosInfo.Name
             : 'unknown';

怎么样

try {
   alert(test.level1.level2.level3)
} catch(e) {
 ...whatever

}