ユーレカ!私はそれを考え出した!以下の回答は、私が書いているライブラリの形式ですが、比較的簡単に理解できるはずです。
結局のところ、(私が知る限り)最善の方法は、最初に別の関数を使用して、すべてのプロパティ パスを含むターゲット オブジェクトからオブジェクトを構築することです。
/**
* 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: [...]
// ...
// }
各プロパティがオブジェクト内のパスにマップされる場所。