Javascript 使用点符号字符串访问对象子属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8051975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:31:27  来源:igfitidea点击:

Access object child properties using a dot notation string

javascriptjquery

提问by msanjay

I'm temporarily stuck with what appears to be a very simple JavaScript problem, but maybe I'm just missing the right search keywords!

我暂时陷入了一个看起来非常简单的 JavaScript 问题,但也许我只是缺少正确的搜索关键字!

Say we have an object

假设我们有一个对象

var r = { a:1, b: {b1:11, b2: 99}};

There are several ways to access the 99:

有几种方法可以访问99:

r.b.b2
r['b']['b2']

What I want is to be able to define a string

我想要的是能够定义一个字符串

var s = "b.b2";

and then access the 99 using

然后使用访问 99

r.s or r[s] //(which of course won't work)

One way is to write a function for it that splits the string on dot and maybe recursively/iteratively gets the property. But is there any simpler/more efficient way? Anything useful in any of the jQuery APIs here?

一种方法是为它编写一个函数,在点上拆分字符串,并可能递归/迭代地获取属性。但是有没有更简单/更有效的方法?在这里的任何 jQuery API 中有什么有用的吗?

回答by Andy E

Here's a naive function I wrote a while ago, but it works for basic object properties:

这是我前一段时间写的一个简单的函数,但它适用于基本的对象属性:

function getDescendantProp(obj, desc) {
    var arr = desc.split(".");
    while(arr.length && (obj = obj[arr.shift()]));
    return obj;
}

console.log(getDescendantProp(r, "b.b2"));
//-> 99

Although there are answers that extend this to "allow" array index access, that's not really necessary as you can just specify numerical indexes using dot notation with this method:

尽管有一些答案将其扩展为“允许”数组索引访问,但这并不是真正必要的,因为您可以使用此方法使用点表示法指定数字索引:

getDescendantProp({ a: [ 1, 2, 3 ] }, 'a.2');
//-> 3

回答by AmmarCSE

splitand reducewhile passing the object as the initalValue

对象作为对象传递时拆分减少initalValue

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce(function(a, b) {
  return a[b];
}, r);

console.log(value);

Update(thanks to comment posted by TeChn4K)

更新(感谢 TeChn4K 发表的评论)

With ES6 syntax, it is even shorter

使用 ES6 语法,它甚至更短

var r = { a:1, b: {b1:11, b2: 99}};
var s = "b.b2";

var value = s.split('.').reduce((a, b) => a[b], r);

console.log(value);

回答by Matheus Dal'Pizzol

You can use lodash get() and set() methods.

您可以使用lodash get() 和 set() 方法

Getting

得到

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

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

Setting

环境

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

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// → 4

回答by Rory McCrossan

If it's possible in your scenario that you could put the entire array variable you're after into a string you could use the eval()function.

如果在您的场景中可以将整个数组变量放入字符串中,则可以使用该eval()函数。

var r = { a:1, b: {b1:11, b2: 99}};
var s = "r.b.b2";
alert(eval(s)); // 99

I can feel people reeling in horror

我能感觉到人们惊恐万分

回答by Jason More

Extending @JohnB's answer, I added a setter value as well. Check out the plunkr at

扩展@JohnB 的答案,我还添加了一个 setter 值。查看 plunkr

http://plnkr.co/edit/lo0thC?p=preview

http://plnkr.co/edit/lo0thC?p=preview

enter image description here

在此处输入图片说明

function getSetDescendantProp(obj, desc, value) {
  var arr = desc ? desc.split(".") : [];

  while (arr.length && obj) {
    var comp = arr.shift();
    var match = new RegExp("(.+)\[([0-9]*)\]").exec(comp);

    // handle arrays
    if ((match !== null) && (match.length == 3)) {
      var arrayData = {
        arrName: match[1],
        arrIndex: match[2]
      };
      if (obj[arrayData.arrName] !== undefined) {
        if (typeof value !== 'undefined' && arr.length === 0) {
          obj[arrayData.arrName][arrayData.arrIndex] = value;
        }
        obj = obj[arrayData.arrName][arrayData.arrIndex];
      } else {
        obj = undefined;
      }

      continue;
    }

    // handle regular things
    if (typeof value !== 'undefined') {
      if (obj[comp] === undefined) {
        obj[comp] = {};
      }

      if (arr.length === 0) {
        obj[comp] = value;
      }
    }

    obj = obj[comp];
  }

  return obj;
}

回答by Nicola Peluchetti

This is the simplest i could do:

这是我能做的最简单的事情:

var accessProperties = function(object, string){
   var explodedString = string.split('.');
   for (i = 0, l = explodedString.length; i<l; i++){
      object = object[explodedString[i]];
   }
   return object;
}
var r = { a:1, b: {b1:11, b2: 99}};

var s = "b.b2";
var o = accessProperties(r, s);
alert(o);//99

回答by Manuel van Rijn

you could also do

你也可以这样做

var s = "['b'].b2";
var num = eval('r'+s);

回答by Ferran Basora

I don't know a supported jQuery API function but I have this function:

我不知道支持的 jQuery API 函数,但我有这个函数:

    var ret = data; // Your object
    var childexpr = "b.b2"; // Your expression

    if (childexpr != '') {
        var childs = childexpr.split('.');
        var i;
        for (i = 0; i < childs.length && ret != undefined; i++) {
            ret = ret[childs[i]];
        }
    }

    return ret;

回答by JohnB

I've extended Andy E's answer, so that it can also handle arrays:

我已经扩展了 Andy E 的答案,以便它也可以处理数组:

function getDescendantProp(obj, desc) {
    var arr = desc.split(".");

    //while (arr.length && (obj = obj[arr.shift()]));

    while (arr.length && obj) {
        var comp = arr.shift();
        var match = new RegExp("(.+)\[([0-9]*)\]").exec(comp);
        if ((match !== null) && (match.length == 3)) {
            var arrayData = { arrName: match[1], arrIndex: match[2] };
            if (obj[arrayData.arrName] != undefined) {
                obj = obj[arrayData.arrName][arrayData.arrIndex];
            } else {
                obj = undefined;
            }
        } else {
            obj = obj[comp]
        }
    }

    return obj;
}

There are probably more efficient ways to do the Regex, but it's compact.

可能有更有效的方法来执行正则表达式,但它很紧凑。

You can now do stuff like:

您现在可以执行以下操作:

var model = {
    "m1": {
        "Id": "22345",
        "People": [
            { "Name": "John", "Numbers": ["07263", "17236", "1223"] },
            { "Name": "Jenny", "Numbers": ["2", "3", "6"] },
            { "Name": "Bob", "Numbers": ["12", "3333", "4444"] }
         ]
    }
}

// Should give you "6"
var x = getDescendantProp(model, "m1.People[1].Numbers[2]");

回答by Iain Ballard

Here is an extension of Andy E's code, that recurses into arrays and returns all values:

这是 Andy E 代码的扩展,它递归到数组中并返回所有值:

function GetDescendantProps(target, pathString) {
    var arr = pathString.split(".");
    while(arr.length && (target = target[arr.shift()])){
        if (arr.length && target.length && target.forEach) { // handle arrays
            var remainder = arr.join('.');
            var results = [];
            for (var i = 0; i < target.length; i++){
                var x = this.GetDescendantProps(target[i], remainder);
                if (x) results = results.concat(x);
            }
            return results;
        }
    }
    return (target) ? [target] : undefined; //single result, wrap in array for consistency
}

So given this target:

因此,鉴于此target

var t = 
{a:
    {b: [
            {'c':'x'},
            {'not me':'y'},
            {'c':'z'}
        ]
    }
};

We get:

我们得到:

GetDescendantProps(t, "a.b.c") === ["x", "z"]; // true