如果我有一个对象的引用:
var test = {};
可能(但不是立即)具有嵌套对象,例如:
{level1: {level2: {level3: "level3"}}};
检查深度嵌套对象中属性是否存在的最佳方法是什么?
alert(test.level1);产生undefined,但alert(test.level1.level2.level3);失败。
alert(test.level1);
undefined
alert(test.level1.level2.level3);
我目前正在做这样的事情:
if(test.level1 && test.level1.level2 && test.level1.level2.level3) { alert(test.level1.level2.level3); }
但我想知道是否有更好的方法。
如果您不想要a,则必须分步执行,TypeError因为如果其中一个成员是null或undefined,并且您尝试访问成员,则将引发异常。
TypeError
null
您可以简单地catch指定异常,也可以创建一个函数来测试是否存在多个级别,如下所示:
catch
function checkNested(obj /*, level1, level2, ... levelN*/) { var args = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < args.length; i++) { if (!obj || !obj.hasOwnProperty(args[i])) { return false; } obj = obj[args[i]]; } return true; } var test = {level1:{level2:{level3:'level3'}} }; checkNested(test, 'level1', 'level2', 'level3'); // true checkNested(test, 'level1', 'level2', 'foo'); // false
ES6更新:
这是原始功能的简化版本,使用了ES6功能和递归功能(也采用正确的尾调用形式):
function checkNested(obj, level, ...rest) { if (obj === undefined) return false if (rest.length == 0 && obj.hasOwnProperty(level)) return true return checkNested(obj[level], ...rest) }
但是,如果要获取嵌套属性的值,而不仅要检查其存在,那么这里有一个简单的单行函数:
function getNested(obj, ...args) { return args.reduce((obj, level) => obj && obj[level], obj) } const test = { level1:{ level2:{ level3:'level3'} } }; console.log(getNested(test, 'level1', 'level2', 'level3')); // 'level3' console.log(getNested(test, 'level1', 'level2', 'level3', 'length')); // 6 console.log(getNested(test, 'level1', 'level2', 'foo')); // undefined console.log(getNested(test, 'a', 'b')); // undefined
上面的函数允许您获取嵌套属性的值,否则将返回undefined。
更新2019-10-17:
在可选的链接建议对达到第3阶段ECMAScript委员会的过程,这将让你安全地访问深度嵌套的性质,通过使用令牌?.,新的 可选链接操作 :
?.
const value = obj?.level1?.level2?.level3
如果所访问的任何级别是null或undefined表达式将undefined自行解析为。
该建议还允许您安全地处理方法调用:
obj?.level1?.method();
上面的表达式将产生undefined如果obj,obj.level1或者obj.level1.method是null或undefined,否则会调用该函数。
obj
obj.level1
obj.level1.method
从Babel 7.8.0开始,默认情况下支持ES2020
更新:2019年12月🎉🎉
可选的链接建议最终在TC39委员会的2019年12月会议上达到了第4阶段。这意味着此功能将成为 ECMAScript 2020 标准的一部分。