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

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?


当前回答

请注意,以下选项并不适用于所有有效的unicode属性名(但据我所知,其他选项也不适用)。

const PATTERN = /[\^|\[|\.]([$|\w]+)/gu function propValue(o, s) { const names = [] for(let [, name] of [...s.matchAll(PATTERN)]) names.push(name) return names.reduce((p, propName) => { if(!p.hasOwnProperty(propName)) throw 'invalid property name' return p[propName] }, o) } let path = 'myObject.1._property2[0][0].$property3' let o = { 1: { _property2: [ [{ $property3: 'Hello World' }] ] } } console.log(propValue(o, path)) // 'Hello World'

其他回答

现在lodash使用_支持这一点。get (obj,财产)。看到https://lodash.com/docs

文档中的例子:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'

如果您想要一个能够正确检测和报告路径解析的任何问题的详细信息的解决方案,我为此编写了自己的解决方案——库路径-值。

const {resolveValue} = require('path-value');

resolveValue(someObject, 'part1.name'); //=> Part 1
resolveValue(someObject, 'part2.qty'); //=> 50
resolveValue(someObject, 'part3.0.name'); //=> Part 3A

请注意,对于索引,我们使用.0,而不是[0],因为解析后者会增加性能损失,而.0直接在JavaScript中工作,因此非常快。

然而,完整的ES5 JavaScript语法也被支持,它只需要首先被标记化:

const {resolveValue, tokenizePath} = require('path-value');

const path = tokenizePath('part3[0].name'); //=> ['part3', '0', 'name']

resolveValue(someObject, path); //=> Part 3A

你可以通过以下简单的技巧,在没有任何外部JavaScript库的情况下,使用点表示法获得deep对象成员的值:

function objectGet(obj, path) { return new Function('_', 'return _.' + path)(obj); };

在你的例子中,要从someObject中获取part1.name的值,只需做:

objectGet(someObject, 'part1.name');

这里是一个简单的小提琴演示:https://jsfiddle.net/harishanchu/oq5esowf/

ES6:只有一行在Vanila JS(它返回null如果没有找到,而不是给出错误):

'path.string'.split('.').reduce((p,c)=>p&&p[c]||null, MyOBJ)

或例子:

'a.b.c'.split('.').reduce((p,c)=>p&&p[c]||null, {a:{b:{c:1}}})

可选链接操作符:

'a.b.c'.split('.').reduce((p,c)=>p?.[c], {a:{b:{c:1}}})

对于一个也识别false, 0和负数并接受默认值作为参数的ready to use函数:

const resolvePath = (object, path, defaultValue) => path
   .split('.')
   .reduce((o, p) => o ? o[p] : defaultValue, object)

示例:

resolvePath(window,'document.body') => <body>
resolvePath(window,'document.body.xyz') => undefined
resolvePath(window,'document.body.xyz', null) => null
resolvePath(window,'document.body.xyz', 1) => 1

奖金:

要设置路径(由@rob-gordon请求),您可以使用:

const setPath = (object, path, value) => path
   .split('.')
   .reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, object)

例子:

let myVar = {}
setPath(myVar, 'a.b.c', 42) => 42
console.log(myVar) => {a: {b: {c: 42}}}

使用[]访问数组:

const resolvePath = (object, path, defaultValue) => path
   .split(/[\.\[\]\'\"]/)
   .filter(p => p)
   .reduce((o, p) => o ? o[p] : defaultValue, object)

例子:

const myVar = {a:{b:[{c:1}]}}
resolvePath(myVar,'a.b[0].c') => 1
resolvePath(myVar,'a["b"][\'0\'].c') => 1

AngularJS有$scope.$eval

在AngularJS中,我们可以使用$scope。$eval方法访问嵌套对象:

$scope.someObject = someObject;
console.log( $scope.$eval("someObject.part3[0].name") ); //Part 3A

有关更多信息,请参见

AngularJS $scope API引用- $eval

演示

angular.module("app",[]) .run(function($rootScope) { $rootScope.someObject = { 'part2' : { 'name': 'Part 2', 'size': '15', 'qty' : '60' }, 'part3' : [{ 'name': 'Part 3A', 'size': '10', 'qty' : '20' },{ name: 'Part 3B' }] }; console.log( "part3[0].name =", $rootScope.$eval("someObject.part3[0].name") ); }) <script src="//unpkg.com/angular/angular.js"></script> <body ng-app="app" </body>