我正在尝试创建一个“解析”对象中嵌套属性的点分隔路径的函数。
所以说你有以下对象:
var obj = {
A: {
A_1: {
},
A_2: {
A_2_a: {},
A_2_b: {
A_2_b_1: {},
A_2_b_2: {},
}
},
A_3: {},
},
B: {
B_1: {
},
B_2: {
B_2_a: {
},
B_2_b: {
B_2_b_1: {},
B_2_b_2: {},
}
},
B_3: {},
},
};
我想在resolve(obj, "B_2_b_2")
之类的对象上调用一个函数,让它返回属性的完整对象路径,即:B.B_2.B_2_b.B_2_b_2
。
答案 0 :(得分:1)
假设一个命名约定,就像在你的示例对象中一样:
function resolve(id) {
var parts = id.split("_");
var path = [];
for (var i=0; i<parts.length; i++)
path.push(parts.slice(0, i+1).join("_"));
return path;
}
> resolve("B_2_b_2")
["B", "B_2", "B_2_b", "B_2_b_2"]
> resolve("B_2_b_2").join(".")
"B.B_2.B_2_b.B_2_b_2"
使用路径数组,您可以轻松递归嵌套对象以获取属性值。
数据对象中的树搜索是微不足道的。但是,我们可以通过假定命名约定来优化它:
function resolve(obj, id) {
if (id in obj)
return [id]; // we've found it
var path;
for (var l=id.length-1; l>0; l--) {
var sub = id.substr(0, l);
if (sub in obj && (path = resolve(obj[sub], id))) {
path.unshift(sub);
return path;
}
}
for (var prop in obj) {
if (path = resolve(obj[prop], id)) {
path.unshift(prop);
return path;
}
}
return null;
}
答案 1 :(得分:1)
尤里卡!我想到了!下面的答案是我正在写的一个库的形式,但它应该相对容易理解。
事实证明,最好的行动方案(据我所知)首先使用一个单独的函数,从包含所有属性路径的目标对象构建一个对象:
/**
* Returns an object containing all of the property paths of an object. Each
* property path is referenced by the property name.
* @param {object} The object to target
* @return {object} Object containing paths ELSE undefined
*/
paths: function( obj, path, lastKey, nextKey ) {
var o, key,
path = path ? path : {},
lastKey = lastKey ? lastKey : "",
nextKey = nextKey ? nextKey : "";
for ( o in obj ) {
// Push path onto stack
path[o] = (nextKey + "." + lastKey + "." + o).replace(/^[.]+/g, "");
// Pass updated "nextKey" along with next recurse
key = nextKey + "." + lastKey;
// Call again on all nested objects
if ( (lib).isPlainObject(obj[o]) ) {
(lib).paths(obj[o], path, o, key);
}
}
return (lib).len(path) ? path : undefined;
},
然后我们使用resolve方法作为paths方法的“包装器”,返回目标属性键的命名空间。
resolve: function( obj, key ) {
return (lib).paths(obj)[key];
},
使用我上面发布的对象:
var res = o.resolve(obj, "A_2_b_1");
// Returns "A.A_2.A_2_b.A_2_b_1"
仅供参考,paths
方法返回一个如下所示的对象:
// {
// A: [...]
// A_1: [...]
// A_2: [...]
// A_2_a: [...]
// A_2_b: [...]
// A_2_b_1: [
// 0: "A_2_b_1"
// 1: "A.A_2.A_2_b.A_2_b_1"
// ]
// A_2_b_2: [...]
// A_2_c: [...]
// A_3: [...]
// B: [...]
// ...
// }
每个属性映射到对象中的路径。