Javascript 使用对象的完整路径访问对象的属性值
我有一个包含许多嵌套元素的对象,如下所示Javascript 使用对象的完整路径访问对象的属性值,javascript,google-chrome,object,nested,Javascript,Google Chrome,Object,Nested,我有一个包含许多嵌套元素的对象,如下所示 var out = { "parentOne":{ "subParentOne":{ "childOne":0, "childTwo":0 }, "subParentTwo":{ "otherChildOne":0, "otherChileTwo":0 } }, "parentTwo":{ [...] }
var out = {
"parentOne":{
"subParentOne":{
"childOne":0,
"childTwo":0
},
"subParentTwo":{
"otherChildOne":0,
"otherChileTwo":0
}
},
"parentTwo":{
[...]
}
}
对象中总共有269个不同的属性
我有一个数组,包含我需要检索的属性的“路径”,如下所示:
var prop = ["parentOne.subParentOne.childOne", "parentOne.subParentTwo.otherChildTwo"]
所以这个数组最多可以包含269个元素
要访问子密钥的值,我使用以下代码:
for (let p in prop) {
var result = out
var keys = prop[p].split(".")
for (let k in keys) {
result = result[keys[k]]
}
// do stuff with the value
}
但它效率很低,所以我正在寻找更好的解决方案
为什么这不起作用
var result = out["parentOne.subParentOne.childOne"]
那么,实现这一目标的最佳方式是什么
(请注意,我正在上面构建我的应用程序,所以我只对google chrome的工作解决方案感兴趣)
编辑:
忘了说对象属性可以更改。当前,在启动应用程序后,我向服务器发送请求,获取示例输出并解析结果,以使用此方法获取可用密钥:
var availableKeys = []
parseKey(out, '')
function parseKey(object, root) {
for (let key in object) {
switch (typeof object[key]) {
case 'object':
parseKey(object[key], (root === '' ? key : root + '.' + key))
break
case 'number':
availableKeys.push((root === '' ? '' : root + '.') + key)
break
default:
break
}
}
}
但它的效率很低
不,不是。它是一个字符串拆分,然后是一个访问对象上几个属性的循环。除了拆分的开销(最小)和循环的开销(最小),它与out.parentOne.subParentOne.childOne一样高效
为什么这不起作用
var result = out["parentOne.subParentOne.childOne"]
因为它正在查找名为parentOne.subParentOne.childOne
的属性,这是JavaScript对象的一个完全有效的属性名:
var out={
“parentOne.subParentOne.childOne”:“这是值”
};
console.log(out[“parentOne.subParentOne.childOne]”)代码>
但它的效率很低
不,不是。它是一个字符串拆分,然后是一个访问对象上几个属性的循环。除了拆分的开销(最小)和循环的开销(最小),它与out.parentOne.subParentOne.childOne
一样高效
为什么这不起作用
var result = out["parentOne.subParentOne.childOne"]
因为它正在查找名为parentOne.subParentOne.childOne
的属性,这是JavaScript对象的一个完全有效的属性名:
var out={
“parentOne.subParentOne.childOne”:“这是值”
};
console.log(out[“parentOne.subParentOne.childOne]”)代码>这不是对如何处理“属性路径”问题的直接回答,例如a.b.c
。TJ Crowder引用的答案涵盖了这一点。这个答案涉及其他方法
一般来说,如果我想进行一些处理,我有两种选择。一个是用我的宿主语言写下A的逻辑。我可以以某种方式将该程序与“名称”关联起来,这样我就可以在需要时查找并执行它。另一种选择是发明一种小语言(通常称为“DSL”),它允许我以“a”的形式更简洁地表达我的处理需求。然后,我为DSL编写一个解释器来解析A’,并实际执行处理A
在您的情况下,您选择了第二种选择。DSL是点分隔的属性路径,如a.b.c
,解析器是您编写的代码。这没有什么问题,也没有真正的性能问题。但这可能没有必要。相反,考虑将度量表示为JS函数:
const myMetrics = {
metric1: obj => obj.parentOne.subParentOne.childOne,
...
}
现在,当用户选择“metric1”
时,只需说出myMetrics[metricName](out)
即可检索所需的度量
这似乎是一个神秘的区别。但是,考虑用户选择的特定度量可能对应于比简单嵌套属性引用更复杂的情况。可能该度量有一个带有日期字段的数组值,您希望为该度量选择最新的值。在这种情况下,使用DSL(属性路径)方法,您需要扩展DSL以允许类似于parentOne.subParentOne[@latest].childOne
,作为示例,并相应地扩展解释器。事情可能会很快失控——不久之后,您可能已经重新实现了jq的等效功能。使用将每个用户可选择的度量直接与JS函数关联的方法,您可以编写任意复杂度的定义。这不是如何处理“属性路径”(如a.b.c
)问题的直接答案。TJ Crowder引用的答案涵盖了这一点。这个答案涉及其他方法
一般来说,如果我想进行一些处理,我有两种选择。一个是用我的宿主语言写下A的逻辑。我可以以某种方式将该程序与“名称”关联起来,这样我就可以在需要时查找并执行它。另一种选择是发明一种小语言(通常称为“DSL”),它允许我以“a”的形式更简洁地表达我的处理需求。然后,我为DSL编写一个解释器来解析A’,并实际执行处理A
在您的情况下,您选择了第二种选择。DSL是点分隔的属性路径,如a.b.c
,解析器是您编写的代码。这没有什么问题,也没有真正的性能问题。但这可能没有必要。相反,考虑将度量表示为JS函数:
const myMetrics = {
metric1: obj => obj.parentOne.subParentOne.childOne,
...
}
现在,当用户选择“metric1”
时,只需说出myMetrics[metricName](out)
即可检索所需的度量
这似乎是一个神秘的区别。但是,考虑用户选择的特定度量可能对应于比简单嵌套属性引用更复杂的情况。可能该度量有一个带有日期字段的数组值,您希望为该度量选择最新的值。在这种情况下,使用DSL(属性路径)方法,您需要扩展DSL以允许类似于parentOne.subParentOne[@latest].childOne
,作为示例,并相应地扩展解释器。事情可能很快就会转危为安