如果我有对象的引用:
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
使现代化
看起来lodash已经为您的所有嵌套属性获取需求添加了_.get。
_.get(countries, 'greece.sparta.playwright')
https://lodash.com/docs#get
上一个答案
lodash用户可能喜欢lodash.contrib,它有几种方法可以缓解这个问题。
获取路径
签名:_.getPath(obj:Object,ks:String|Array)
基于所描述的路径获取嵌套对象中任何深度处的值给出的钥匙。键可以以数组或点分隔字符串的形式给出。如果无法到达路径,则返回undefined。
var countries = {
greece: {
athens: {
playwright: "Sophocles"
}
}
}
};
_.getPath(countries, "greece.athens.playwright");
// => "Sophocles"
_.getPath(countries, "greece.sparta.playwright");
// => undefined
_.getPath(countries, ["greece", "athens", "playwright"]);
// => "Sophocles"
_.getPath(countries, ["greece", "sparta", "playwright"]);
// => undefined
基于这个答案,我使用ES2015提出了一个通用函数,可以解决这个问题
function validChain( object, ...keys ) {
return keys.reduce( ( a, b ) => ( a || { } )[ b ], object ) !== undefined;
}
var test = {
first: {
second: {
third: "This is not the key your are looking for"
}
}
}
if ( validChain( test, "first", "second", "third" ) ) {
console.log( test.first.second.third );
}
//Just in case is not supported or not included by your framework
//***************************************************
Array.prototype.some = function(fn, thisObj) {
var scope = thisObj || window;
for ( var i=0, j=this.length; i < j; ++i ) {
if ( fn.call(scope, this[i], i, this) ) {
return true;
}
}
return false;
};
//****************************************************
function isSet (object, string) {
if (!object) return false;
var childs = string.split('.');
if (childs.length > 0 ) {
return !childs.some(function (item) {
if (item in object) {
object = object[item];
return false;
} else return true;
});
} else if (string in object) {
return true;
} else return false;
}
var object = {
data: {
item: {
sub_item: {
bla: {
here : {
iam: true
}
}
}
}
}
};
console.log(isSet(object,'data.item')); // true
console.log(isSet(object,'x')); // false
console.log(isSet(object,'data.sub_item')); // false
console.log(isSet(object,'data.item')); // true
console.log(isSet(object,'data.item.sub_item.bla.here.iam')); // true