如果我有对象的引用:
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);
}
但我想知道是否有更好的方法。
根据@Stephane LaFlèche的回答,我提出了另一个剧本版本。
JSFiddle演示
var obj = {"a":{"b":{"c":"Hello World"}},"resTest":"potato","success":"This path exists"};
checkForPathInObject = function(object,path,value) {
var pathParts = path.split("."),
result = false;
// Check if required parameters are set; if not, return false
if(!object || typeof object == 'undefined' || !path || typeof path != 'string')
return false;
/* Loop through object keys to find a way to the path or check for value
* If the property does not exist, set result to false
* If the property is an object, update @object
* Otherwise, update result */
for(var i=0;i<pathParts.length;i++){
var currentPathPart = pathParts[i];
if(!object.hasOwnProperty( currentPathPart )) {
result = false;
} else if (object[ currentPathPart ] && path == pathParts[i]) {
result = pathParts[i];
break;
} else if(typeof object[ currentPathPart ] == 'object') {
object = object[ currentPathPart ];
} else {
result = object[ currentPathPart ];
}
}
/* */
if(typeof value != 'undefined' && value == result)
return true;
return result;
};
// Uncomment the lines below to test the script
// alert( checkForPathInObject(obj,'a.b.c') ); // Results "Hello World"
// alert( checkForPathInObject(obj,'a.success') ); // Returns false
// alert( checkForPathInObject(obj,'resTest', 'potato') ); // Returns true
这是我使用的一个小助手函数,对我来说,它非常简单明了。希望这对一些人有帮助:)。
static issetFromIndices(param, indices, throwException = false) {
var temp = param;
try {
if (!param) {
throw "Parameter is null.";
}
if(!Array.isArray(indices)) {
throw "Indices parameter must be an array.";
}
for (var i = 0; i < indices.length; i++) {
var index = indices[i];
if (typeof temp[index] === "undefined") {
throw "'" + index + "' index is undefined.";
}
temp = temp[index];
}
} catch (e) {
if (throwException) {
throw new Error(e);
} else {
return false;
}
}
return temp;
}
var person = {
hobbies: {
guitar: {
type: "electric"
}
}
};
var indices = ["hobbies", "guitar", "type"];
var throwException = true;
try {
var hobbyGuitarType = issetFromIndices(person, indices, throwException);
console.log("Yay, found index: " + hobbyGuitarType);
} catch(e) {
console.log(e);
}
我尝试了递归方法:
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';