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

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?


当前回答

受到@webjay的回答的启发: https://stackoverflow.com/a/46008856/4110122

我做了这个函数,你可以用它来获取/设置/取消设置对象中的任何值

function Object_Manager(obj, Path, value, Action) 
{
    try
    {
        if(Array.isArray(Path) == false)
        {
            Path = [Path];
        }

        let level = 0;
        var Return_Value;
        Path.reduce((a, b)=>{
            level++;
            if (level === Path.length)
            {
                if(Action === 'Set')
                {
                    a[b] = value;
                    return value;
                }
                else if(Action === 'Get')
                {
                    Return_Value = a[b];
                }
                else if(Action === 'Unset')
                {
                    delete a[b];
                }
            } 
            else 
            {
                return a[b];
            }
        }, obj);
        return Return_Value;
    }

    catch(err)
    {
        console.error(err);
        return obj;
    }
}

使用它:

 // Set
 Object_Manager(Obj,[Level1,Level2,Level3],New_Value, 'Set');

 // Get
 Object_Manager(Obj,[Level1,Level2,Level3],'', 'Get');

 // Unset
 Object_Manager(Obj,[Level1,Level2,Level3],'', 'Unset');

其他回答

我正在用React开发网上商店。我尝试在复制的状态对象中更改值,以在提交时更新原始状态。 上面的例子没有为我工作,因为他们中的大多数突变复制对象的结构。我找到了访问和更改深嵌套对象属性值的函数的工作示例:https://lowrey.me/create-an-object-by-path-in-javascript-2/

const createPath = (obj, path, value = null) => {
  path = typeof path === 'string' ? path.split('.') : path;
  let current = obj;
  while (path.length > 1) {
    const [head, ...tail] = path;
    path = tail;
    if (current[head] === undefined) {
      current[head] = {};
    }
    current = current[head];
  }
  current[path[0]] = value;
  return obj;
};

我只是基于一些类似的代码,我已经有了,它似乎工作:

Object.byString = function(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

用法::

Object.byString(someObj, 'part3[0].name');

在http://jsfiddle.net/alnitak/hEsys/上可以看到一个工作演示

有些人注意到,如果传递的字符串中最左边的索引与对象中正确嵌套的条目不对应,这段代码将抛出错误。这是一个有效的问题,但我认为最好在调用时使用try / catch块来解决,而不是让这个函数对于无效的索引无声地返回undefined。

你必须自己解析字符串:

function getProperty(obj, prop) {
    var parts = prop.split('.');

    if (Array.isArray(parts)) {
        var last = parts.pop(),
        l = parts.length,
        i = 1,
        current = parts[0];

        while((obj = obj[current]) && i < l) {
            current = parts[i];
            i++;
        }

        if(obj) {
            return obj[last];
        }
    } else {
        throw 'parts is not valid array';
    }
}

这要求你也用点表示法定义数组下标:

var part3name1 = "part3.0.name";

它使解析更容易。

DEMO

请注意,以下选项并不适用于所有有效的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'

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

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