JavaScript: 转换字符串并拼接动态创建对象属性引用

JavaScript: Convert string and concatenate it to dynamically create an object property reference

我正在创建一个 API,其中值由服务器通过数据属性传递,因此 JS 可以用来检索信息...我的 JS 进行 AJAX 调用和 JSON 返回对象...

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

为了得到牌子,我直接输入

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

这样我可以获得我需要的结果,但我需要通过加入路径的 2 个部分来动态构建此路径。就像我在问题开头所说的那样,一些信息是通过数据属性传递的,信息是 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() 时进行这种测试。

所以...基本上,我需要的是动态构建 属性 路径的更好方法,可以测试该路径以查看 属性 是否存在...

提前致谢...

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

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

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

不支持括号,所以支持:

type.0.whatever.keys

到 return undefined for non existent keys (instead of an empty object):

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

您可以先检查data.result是否有属性,然后才使您的变量品牌:

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

您可以String#match to find all keys, then iterate the keys using 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);