如果我有对象的引用:
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);
}
但我想知道是否有更好的方法。
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
这有一个小模式,但在某些时候可能会让人不知所措。我建议您一次使用两个或三个嵌套。
if (!(foo.bar || {}).weep) return;
// Return if there isn't a 'foo.bar' or 'foo.bar.weep'.
正如我可能忘记提到的,你也可以进一步扩展。下面的示例显示了对嵌套foo.bar.weep.woop的检查,如果没有可用的,则返回。
if (!((foo.bar || {}).weep || {}).woop) return;
// So, return if there isn't a 'foo.bar', 'foo.bar.weep', or 'foo.bar.weep.woop'.
// More than this would be overwhelming.
今天刚刚编写了这个函数,它对嵌套对象中的属性进行了深入搜索,如果找到了,则返回该属性的值。
/**
* 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;
}