尤里卡!我想到了!下面的答案是我正在编写的库的形式,但它应该相对容易理解。
事实证明,最好的做法(据我所知)是首先使用一个单独的函数,从包含所有属性路径的目标对象构建一个对象:
/**
* 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: [...]
// ...
// }
每个属性映射到其在对象中的路径。