如果我有对象的引用:
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);
}
但我想知道是否有更好的方法。
这适用于所有对象和阵列:)
ex:
if( obj._has( "something.['deep']['under'][1][0].item" ) ) {
//do something
}
这是我对Brian答案的改进版
我使用_has作为属性名称,因为它可能与现有的has属性(例如:maps)冲突
Object.defineProperty( Object.prototype, "_has", { value: function( needle ) {
var obj = this;
var needles = needle.split( "." );
var needles_full=[];
var needles_square;
for( var i = 0; i<needles.length; i++ ) {
needles_square = needles[i].split( "[" );
if(needles_square.length>1){
for( var j = 0; j<needles_square.length; j++ ) {
if(needles_square[j].length){
needles_full.push(needles_square[j]);
}
}
}else{
needles_full.push(needles[i]);
}
}
for( var i = 0; i<needles_full.length; i++ ) {
var res = needles_full[i].match(/^((\d+)|"(.+)"|'(.+)')\]$/);
if (res != null) {
for (var j = 0; j < res.length; j++) {
if (res[j] != undefined) {
needles_full[i] = res[j];
}
}
}
if( typeof obj[needles_full[i]]=='undefined') {
return false;
}
obj = obj[needles_full[i]];
}
return true;
}});
这是小提琴
一个简短的ES5版本@CMS的优秀答案:
// Check the obj has the keys in the order mentioned. Used for checking JSON results.
var checkObjHasKeys = function(obj, keys) {
var success = true;
keys.forEach( function(key) {
if ( ! obj.hasOwnProperty(key)) {
success = false;
}
obj = obj[key];
})
return success;
}
通过类似测试:
var test = { level1:{level2:{level3:'result'}}};
utils.checkObjHasKeys(test, ['level1', 'level2', 'level3']); // true
utils.checkObjHasKeys(test, ['level1', 'level2', 'foo']); // false
根据@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