Javascript 反射:获取嵌套对象路径

6
在这个stackoverflow的帖子中,我学到了可以通过一个简单的字符串获取对象路径。 使用字符串键访问嵌套的JavaScript对象 考虑以下内容:
var person = { name: "somename", personal: { weight: "150", color: "dark" }};

var personWeight = deep_value(person,"personal.weight");

我正在尝试从我的“person”对象中构建一个值不是“object”类型的对象值数组。因此,该数组将如下所示:
[['name', []],['personal.weight', []],['personal.color', []]];

我希望它们以那种形式呈现,因为我将来还会进一步使用它。

这是我尝试过的:

var toIterate = { name: "somename", personal: { age: "19", color: "dark" } }

var myArray = [];

$.each(toIterate, recursive);

function recursive(key, value) {         

    if (key !== null) {
        myArray.push([key, []]);
    }
    else {
        $.each(value, recursive);
    }
}

console.log(myArray);

如果你的结果将拥有所有其他属性,为什么要传递特定属性 personal.weight - DontVoteMeDown
我不确定你的意思是什么。 - TotalWar
如果我理解正确的话,你想要一个新的函数来产生那个结果,实际上与函数 deep_value 没有任何关系,是吗? - DontVoteMeDown
我想要一个函数来生成一个对象的字符串路径表示,以便我可以将其提供给deep_value函数。我会发布我找到的答案,但它并不是非常高效的。 - TotalWar
事实上,那不是正确的。所有与您的问题有关的内容都应该在主贴中,包括您的代码。我已经将您的代码添加到了您的主要问题中,您应该删除那个回答。 - DontVoteMeDown
4个回答

11
使用递归来遍历对象。

var person = {
    name: "somename",
    personal: {
        weight: "150",
        color: "dark",
        foo: {
            bar: 'bar',
            baz: 'baz'
        },
        empty: {
        }
    }
};

// however you want to do this
var isobject = function(x){
    return Object.prototype.toString.call(x) === '[object Object]';
};

var getkeys = function(obj, prefix){
    var keys = Object.keys(obj);
    prefix = prefix ? prefix + '.' : '';
    return keys.reduce(function(result, key){
        if(isobject(obj[key])){
            result = result.concat(getkeys(obj[key], prefix + key));
        }else{
            result.push(prefix + key);
        }
        return result;
    }, []);
};

var keys = getkeys(person);

document.body.innerHTML = '<pre>' + JSON.stringify(keys) + '</pre>';

然后使用 Array.prototype.map 将键的数组转换为你喜欢的格式。 注意 person.personal.empty 的行为。

这似乎是一种奇怪的存储对象键的方式。我想知道你'将来用它做什么'。


2

这是对我有效的方法。请注意,首先创建了一个raw映射,然后将其mapped到一个join中,用.连接Array中的items

var toIterate = {
  name: "somename",
  personal: {
    age: "19",
    color: "dark"
  }
};

console.log(getObjPath(toIterate).map(item => item.join('.')));

function isObject(x) {
  return Object.prototype.toString.call(x) === '[object Object]';
};

function getObjPath(obj, pathArray, busArray) {
  pathArray = pathArray ? pathArray : [];
  if (isObject(obj)) {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (isObject(obj[key])) {
          busArray = busArray ? bussArray : [];
          busArray.push(key);
          getObjPath(obj[key], pathArray, busArray);
        } else {
          if (busArray) {
            pathArray.push(busArray.concat([key]));
          } else {
            pathArray.push([key]);
          }
        }
      }
    }
  }
  return pathArray;
}

祝你好运...


0

0

我相信问题中链接的topic的唯一存在是源自点符号表示的字符串路径。

然而,如果你首先需要解析所有路径,那么你完全可以消除字符串点符号,减轻自己不必要的工作。

假设你的模式是以以下形式:

const obj = { name: "somename", personal: { weight: "150", color: "dark" }};

那么最好将路径收集在一个数组中,例如

const paths = [["name"], ["personal","weight"], ["personal","color"]]

这样获取任何嵌套值现在就像吃蛋糕一样简单。例如:

paths[1].reduce((value,path) => value[path], obj); // 150

让我们看看它的实际效果。

function keyPaths(schema, ...keys){
  return Object.keys(schema)
               .reduce( (r,k) => ( typeof schema[k] === "object" ? r.push(...keyPaths(schema[k],...keys,k))
                                                                 : r.push([...keys,k])
                                 , r
                                 )
                      , []          
                      );                         
}

const obj    = { name: "somename", personal: { weight: "150", color: "dark" }},
      paths  = keyPaths(obj),
      result = paths[1].reduce((value,path) => value[path], obj);

console.log(JSON.stringify(paths,""));
console.log(result);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接