如果我有对象的引用:
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);
}
但我想知道是否有更好的方法。
我编写了自己的函数,该函数采用所需的路径,并具有一个好的和坏的回调函数。
function checkForPathInObject(object, path, callbackGood, callbackBad){
var pathParts = path.split(".");
var currentObjectPath = object;
// Test every step to see if it exists in object
for(var i=0; i<(pathParts.length); i++){
var currentPathPart = pathParts[i];
if(!currentObjectPath.hasOwnProperty(pathParts[i])){
if(callbackBad){
callbackBad();
}
return false;
} else {
currentObjectPath = currentObjectPath[pathParts[i]];
}
}
// call full path in callback
callbackGood();
}
用法:
var testObject = {
level1:{
level2:{
level3:{
}
}
}
};
checkForPathInObject(testObject, "level1.level2.level3", function(){alert("good!")}, function(){alert("bad!")}); // good
checkForPathInObject(testObject, "level1.level2.level3.levelNotThere", function(){alert("good!")}, function(){alert("bad!")}); //bad
今天刚刚编写了这个函数,它对嵌套对象中的属性进行了深入搜索,如果找到了,则返回该属性的值。
/**
* Performs a deep search looking for the existence of a property in a
* nested object. Supports namespaced search: Passing a string with
* a parent sub-object where the property key may exist speeds up
* search, for instance: Say you have a nested object and you know for
* certain the property/literal you're looking for is within a certain
* sub-object, you can speed the search up by passing "level2Obj.targetProp"
* @param {object} obj Object to search
* @param {object} key Key to search for
* @return {*} Returns the value (if any) located at the key
*/
var getPropByKey = function( obj, key ) {
var ret = false, ns = key.split("."),
args = arguments,
alen = args.length;
// Search starting with provided namespace
if ( ns.length > 1 ) {
obj = (libName).getPropByKey( obj, ns[0] );
key = ns[1];
}
// Look for a property in the object
if ( key in obj ) {
return obj[key];
} else {
for ( var o in obj ) {
if ( (libName).isPlainObject( obj[o] ) ) {
ret = (libName).getPropByKey( obj[o], key );
if ( ret === 0 || ret === undefined || ret ) {
return ret;
}
}
}
}
return false;
}
我也遇到了同样的问题,我想看看是否能找到自己的解决方案。这接受要检查的路径作为字符串。
function checkPathForTruthy(obj, path) {
if (/\[[a-zA-Z_]/.test(path)) {
console.log("Cannot resolve variables in property accessors");
return false;
}
path = path.replace(/\[/g, ".");
path = path.replace(/]|'|"/g, "");
path = path.split(".");
var steps = 0;
var lastRef = obj;
var exists = path.every(key => {
var currentItem = lastRef[path[steps]];
if (currentItem) {
lastRef = currentItem;
steps++;
return true;
} else {
return false;
}
});
return exists;
}
下面是一些日志记录和测试用例的片段:
console.clear();var测试案例=[[“data.Messages[0].Code”,true],[“data.Messages[1].Code”,true],[“data.Messages[0]['Code']”,true],['data.Messages[0][“Code”]',true],[“data[Messages][0]['Code']”,错误],[“data['Messages'][0]['Code']”,真]];var path=“data.Messages[0].Code”;变量obj={数据:{消息:[{代码:“0”}, {代码:“1”}]}}函数checkPathForTruthy(obj,路径){if(/\[[a-zA-Z_]/.test(路径)){console.log(“无法解析属性访问器中的变量”);return false;}path=路径替换(/\[/g,“.”);path=路径替换(/]|'|“/g,”“);path=路径拆分(“.”);var步数=0;var lastRef=obj;var logOutput=[];var exists=path.every(key=>{var currentItem=lastRef[path[steps]];if(currentItem){logOutput.push(currentItem);lastRef=当前项;步骤++;返回true;}其他{return false;}});console.log(存在,logOutput);返回存在;}testCase.forEach(testCase=>{如果(checkPathForTruthy(obj,testCase[0])==testCase[1]){console.log(“通过:”+testCase[0]);}其他{console.log(“失败:”+testCase[0]+“预期”+testCase[1]);}});