JavaScript:转换字符串并连接它以动态创建对象属性参考

问题描述:

我创建了一个API,其中值由服务器通过数据属性传递,所以JS可以用来检索信息...我的JS使AJAX调用并返回一个JSON对象...JavaScript:转换字符串并连接它以动态创建对象属性参考

{ 
    "data": { 
     "results": { 
      "type": [ 
       { 
        "cars" : { 
         "brands": { 
          "ford" : {}, 
          "honda" : {} 
         } 
        } 
       } 
      ] 
     } 
    } 
} 

为了获得品牌,我只需要输入

let brand = data.result.type[0].cars.brands.ford 

这样我能得到我需要的结果,但我需要建立这个通过连接路径的两个部分来动态地生成路径。就像我在问题开始时所说的,一些信息通过数据属性传递,信息是type[0].cars.brands.ford ...我需要在我的代码中加入到data.result。我目前能够使用eval()得到期望的结果,像这样

entry.querySelectorAll('[data-brand]').forEach((e) => 
    let brand = eval('data.result.' + e.dataset.brand); 
) 

我知道你们许多人会说,使用eval()是坏的,我很清楚这一点,但是我就是无法找到一个更好的方法来实现这一点,还有另外一个问题,比如当品牌,比如nissan不在JSON上,我得到一个错误TypeError: Cannot read property 'nissan' of undefined ......可以通过检查属性是否存在,继续执行代码,但当涉及eval()时,我不知道如何进行这种测试。

所以...基本上,我需要的,是一个更好的方式来动态地构建属性路径,可测试,看是否存在财产...

在此先感谢...

+1

您可以使用data.result [ 'PROPERTY_NAME'] – Danmoreng

+0

感谢您的答案,但我已经尝试过,并没有工作... –

+0

什么不工作? – Danmoreng

const brand = e.dataset.brand.split(".").reduce((obj,id) => obj[id] || {}, data.results); 

这doenst支架,所以做:

type.0.whatever.keys 

要返回未定义不存在键(而不是一个空的对象):

const brand = e.dataset.brand.split(".").reduce((obj,id) => (obj || {})[id], data.results); 
+0

非常感谢你...我没有知道'reduce()'...我会学习更多...它完美的工作......我只需要调整数据属性,将'type [0] .cars.brands.ford' 'type.0.cars。brands.ford' –

+0

@paulo youre welcome;) –

+0

只是一个问题...我stil获取TypeError:无法读取undefined'的属性'sentra',因为品牌nissan没有设置...所以,基本上这不存在'type.0.cars.brands.nissan.sentra' ...当父属性不存在时,如何停止'reduce()'迭代?你知道吗? –

您可以检查,即允许您使用路径访问对象的值的lodash get方法。

如果lodash对您来说太大,只需查看它们的实现。

+0

感谢您的帮助,但我相信lodash是为我的需要大... –

您可以检查数据。结果有财产第一,然后才使您的变量品牌:

if(data.result.hasOwnProperty(e.dataset.brand)){ 
    let brand = data.result[e.dataset.brand]; 
} 
+0

我已经尝试过,但它不工作...我得到'undefined'作为结果... –

+0

如果'data.result'没有您正在循环的品牌,就会发生这种情况。 – Danmoreng

您可以String#match找到所有的键,然后用Array#reduce迭代的钥匙,并从对象获取键值:

const obj = {"data":{"results":{"type":[{"cars":{"brands":{"ford":{"name":"ford"},"honda":{"name":"honda"}}}}]}}}; 
 

 
const brand = 'data.results.type[0].cars.brands.ford'; 
 

 
const getPathValue = (src, path) => path.match(/[^.\[\]]+/g) 
 
    .reduce((p, k) => typeof p === 'object' ? p[k] : p, src); 
 

 
const brandOBj = getPathValue(obj, brand); 
 

 
console.log(brandOBj);