javascript - 检索对象中最深层属性的路径

标签 javascript javascript-objects nested-object

我正在尝试找到一种方法来动态创建一个数组,该数组包含嵌套对象中最深层属性的路径。例如,如果我的对象如下:

{
    userName: [],
    email: [],
    name: {
        fullName: [],
        split: {
            first: [],
            last: []
        }
    },
    date: {
        input: {
            split: {
                month: [],
                year: []
            },
            full: []
        },
        select: {
            month: [],
            year: []
        }
    }
};

我需要一个数组来包含类似的内容:

["userName", "email", "name.fullName", "name.split.first",...]

是否有任何内置或外部库可以自动执行此操作?我试图在父对象上使用 Object.keys 但这只返回直接子属性。

最佳答案

您可以使用Array.prototype.flatMap为此-

const d =
  {userName:[],email:[],name:{fullName:[],split:{first:[],last:[]}},date:{input:{split:{month:[],year:[]},full:[]},select:{month:[],year:[]}}}

const main = (o = {}, path = []) =>
  Array.isArray(o) || Object(o) !== o
    ? [ path ]
    : Object
        .entries(o)
        .flatMap(([ k, v ]) => main(v, [...path, k ]))
        
console.log(main(d))

输出

[ [ "userName" ]
, [ "email" ]
, [ "name", "fullName" ]
, [ "name" ,"split", "first" ]
, [ "name", "split", "last" ]
, ...
]
<小时/>

如果您希望路径为 "a.b.c"而不是[ "a", "b", "c" ] ,使用.mapArray.prototype.join -

const d =
  {userName:[],email:[],name:{fullName:[],split:{first:[],last:[]}},date:{input:{split:{month:[],year:[]},full:[]},select:{month:[],year:[]}}}

const main = (o = {}, path = []) =>
  Array.isArray(o) || Object(o) !== o
    ? [ path ]
    : Object
        .entries(o)
        .flatMap(([ k, v ]) => main(v, [...path, k ]))
        
console.log(main(d).map(path => path.join(".")))

输出

[
  "userName",
  "email",
  "name.fullName",
  "name.split.first",
  "name.split.last",
  "date.input.split.month",
  "date.input.split.year",
  "date.input.full",
  "date.select.month",
  "date.select.year"
]
<小时/>

如果您不想依赖Array.prototype.flatMap由于您的环境不支持它,因此您可以使用 Array.prototype.reduce 的组合和Array.prototype.concat -

const d =
  {userName:[],email:[],name:{fullName:[],split:{first:[],last:[]}},date:{input:{split:{month:[],year:[]},full:[]},select:{month:[],year:[]}}}

const main = (o = {}, path = []) =>
  Array.isArray(o) || Object(o) !== o
    ? [ path ]
    : Object
        .entries(o)
        .reduce // <-- manual flatMap
          ( (r, [ k, v ]) =>
              r.concat(main(v, [...path, k ]))
          , []
          )
        
console.log(main(d).map(path => path.join(".")))

<小时/>

或者你可以填充 Array.prototype.flatMap -

Array.prototype.flatMap = function (f, context)
{ return this.reduce
    ( (r, x, i, a) => r.concat(f.call(context, r, x, i, a))
    , []
    )
}
<小时/>

Is there a way to access any of those properties' value? Eg. "d.name.split.first" using the returned array at position 3?

我们可以编写一个接受对象的查找函数,o ,以及点分隔的字符串 s ,如果可能的话返回一个值,否则返回 undefined如果s无法访问 -

const d =
  {userName:[],email:[],name:{fullName:[],split:{first:[],last:[]}},date:{input:{split:{month:[],year:[]},full:[]},select:{month:[],year:[]}}}
  
const lookup = (o = {}, s = "") =>
  s
    .split(".")
    .reduce
      ( (r, x) =>
          r == null ? undefined : r[x]
      , o
      )
 
console.log(lookup(d, "name.split"))
// { first: [], last: [] }

console.log(lookup(d, "name.split.first"))
// []

console.log(lookup(d, "name.split.zzz"))
// undefined

console.log(lookup(d, "zzz"))
// undefined

关于javascript - 检索对象中最深层属性的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57778629/

相关文章:

javascript - Angular 9-更改 app.module.ts 中的 Angular Material 日期格式不会更改惰性模块中的日期选择器格式

javascript - Bootstrap v4.3 Navbar 没有正确动画折叠的非导航栏元素的显示过渡

javascript - rollupjs 和 sapper - 未定义要求

JavaScript:在 while 循环中更改对象中的值

javascript - 如何使用 jQuery 合并两个 json 对象?

JavaScript 数组和对象映射

javascript - 无法读取 JSON - 无法读取未定义的属性

javascript - 如何为 jquery 插件执行嵌套对象?

javascript - 简化嵌套的 javascript 对象

node.js - Mongoose - 查询深度嵌套的对象