我有一个这样的数据结构:

var someObject = {
    'part1' : {
        'name': 'Part 1',
        'size': '20',
        'qty' : '50'
    },
    'part2' : {
        'name': 'Part 2',
        'size': '15',
        'qty' : '60'
    },
    'part3' : [
        {
            'name': 'Part 3A',
            'size': '10',
            'qty' : '20'
        }, {
            'name': 'Part 3B',
            'size': '5',
            'qty' : '20'
        }, {
            'name': 'Part 3C',
            'size': '7.5',
            'qty' : '20'
        }
    ]
};

我想使用这些变量访问数据:

var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";

part1name应该用someObject.part1.name的值填充,即“Part 1”。part2quantity也是一样,它的容量是60。

有没有办法实现这与纯javascript或JQuery?


当前回答

这个解决方案怎么样:

setJsonValue: function (json, field, val) {
  if (field !== undefined){
    try {
      eval("json." + field + " = val");
    }
    catch(e){
      ;
    }
  }  
}

这个,用来得到:

getJsonValue: function (json, field){
  var value = undefined;
  if (field !== undefined) {
    try {
      eval("value = json." + field);
    } 
    catch(e){
      ;
    }
  }
  return value;
};

可能有些人会认为它们不安全,但它们解析字符串的速度肯定要快得多。

其他回答

这是我使用的解决方案:

function resolve(path, obj=self, separator='.') {
    var properties = Array.isArray(path) ? path : path.split(separator)
    return properties.reduce((prev, curr) => prev?.[curr], obj)
}

使用示例:

// accessing property path on global scope
resolve("document.body.style.width")
// or
resolve("style.width", document.body)

// accessing array indexes
// (someObject has been defined in the question)
resolve("part3.0.size", someObject) // returns '10'

// accessing non-existent properties
// returns undefined when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})

// accessing properties with unusual keys by changing the separator
var obj = { object: { 'a.property.name.with.periods': 42 } }
resolve('object->a.property.name.with.periods', obj, '->') // returns 42

// accessing properties with unusual keys by passing a property name array
resolve(['object', 'a.property.name.with.periods'], obj) // returns 42

限制:

不能将方括号([])用于数组下标-尽管在分隔符令牌之间指定数组下标(例如,.)可以正常工作,如上所示。

这是一个有lodash的单班轮。

const deep = { l1: { l2: { l3: "Hello" } } };
const prop = "l1.l2.l3";
const val = _.reduce(prop.split('.'), function(result, value) { return result ? result[value] : undefined; }, deep);
// val === "Hello"

或者更好……

const val = _.get(deep, prop);

或ES6版本w/ reduce…

const val = prop.split('.').reduce((r, val) => { return r ? r[val] : undefined; }, deep);

普伦克尔

DotObject = obj => new Proxy(obj, { Get:函数(o,k) { Const m = k.match(/(.+?)\.(.+)/) 返回m ?这一点。Get (o[m[1]], m[2]): o[k] } }) const test = DotObject({a: {b: {c: 'wow'}}}) console.log(测试[' a.b.c '])

虽然reduce很好,但我很惊讶没有人使用forEach:

function valueForKeyPath(obj, path){
        const keys = path.split('.');
        keys.forEach((key)=> obj = obj[key]);
        return obj;
    };

Test

我还没有找到一个包来使用字符串路径执行所有操作,所以我最终编写了自己的快速小包,它支持insert(), get()(默认返回),set()和remove()操作。

您可以使用点表示法、括号、数字索引、字符串数字属性以及非单词字符的键。简单用法如下:

> var jsocrud = require('jsocrud');

...

// Get (Read) ---
> var obj = {
>     foo: [
>         {
>             'key w/ non-word chars': 'bar'
>         }
>     ]
> };
undefined

> jsocrud.get(obj, '.foo[0]["key w/ non-word chars"]');
'bar'

https://www.npmjs.com/package/jsocrud

https://github.com/vertical-knowledge/jsocrud