如果我有对象的引用:
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);
}
但我想知道是否有更好的方法。
CMS解决方案工作得很好,但使用/语法可能更方便。我建议如下
var checkNested = function(obj, structure) {
var args = structure.split(".");
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
还有一个非常紧凑的:
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
下面是我的看法-这些解决方案中的大多数都忽略了嵌套数组的情况,如:
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));
var a;
a = {
b: {
c: 'd'
}
};
function isset (fn) {
var value;
try {
value = fn();
} catch (e) {
value = undefined;
} finally {
return value !== undefined;
}
};
// ES5
console.log(
isset(function () { return a.b.c; }),
isset(function () { return a.b.c.d.e.f; })
);
如果您在ES6环境中编码(或使用6to5),则可以利用箭头函数语法:
// ES6 using the arrow function
console.log(
isset(() => a.b.c),
isset(() => a.b.c.d.e.f)
);
关于性能,使用try没有性能惩罚。。如果设置了属性,则捕获块。如果属性未设置,则会影响性能。
考虑简单地使用_.has:
var object = { 'a': { 'b': { 'c': 3 } } };
_.has(object, 'a');
// → true
_.has(object, 'a.b.c');
// → true
_.has(object, ['a', 'b', 'c']);
// → true