Javascript 如何返回对象中属性的命名空间路径?

Javascript 如何返回对象中属性的命名空间路径?,javascript,Javascript,我试图创建一个函数,用于“解析”对象中嵌套属性的点分隔路径 假设您有以下对象: var obj = { A: { A_1: { }, A_2: { A_2_a: {}, A_2_b: { A_2_b_1: {}, A_2_b_2: {}, } }, A_3: {},

我试图创建一个函数,用于“解析”对象中嵌套属性的点分隔路径

假设您有以下对象:

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
假设命名约定,如您的示例对象:

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"

尤里卡!我知道了!下面的答案是以我正在编写的库的形式给出的,但应该相对容易理解

事实证明,最好的做法(据我所知)是首先使用一个单独的函数,从包含所有属性路径的目标对象构建一个对象:

/**
 * 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: [...]
    // ...
// }

每个属性映射到其在对象中的路径。

如果相同的属性名称在
obj
中出现两次会怎样?到目前为止您尝试了什么?你会发布一两条你最好的“失败的尝试”吗?或者,你只想用下划线分割?请编辑你的问题,将你的示例代码替换为“尝试了很多次”(从问题中删除为不相关)。我创建了一个基本上做到这一点的脚本:--正如你所看到的,这不是最简单的事情,所以也许你应该问一个更具体的问题嗯。。所以,基本上先创建一个路径数组,然后在执行搜索时在对象上迭代,我只会查找hasOwnProperty匹配?隐马尔可夫模型。。你可能发现了什么。我要试试。等等,不,看这不起作用:这将假定属性的路径将保持给定的命名约定。这不是我的意图。你没有命名约定吗?那你在找什么呢?否则,属性名称可能会出现在对象中的任何位置(和多次)。如果属性名称出现多次,则我将返回该属性名称的第一个找到的实例的路径。您知道,对象键没有顺序,因此函数可能会为同一对象返回不同的结果?请,将
resolve
方法更改为简单的
返回库路径(obj)[key]
并从阵列中删除密钥。顺便说一句,仅仅为了查找一条路径而构建一个完整的
路径
对象是一个非常低效的好主意。谢谢你的建议!当我试图解决一个问题时,我倾向于用更具解释性的方式来写东西。然后我重构。但你绝对正确。谢谢。关于效率:在库实现中,给定对象的路径只计算一次,链中的方法将访问该数据。
// {
    // 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: [...]
    // ...
// }