以点表示法转换字符串以获取对象引用

IT技术 javascript object syntax
2021-02-10 12:54:16

在javascript中考虑这个对象,

var obj = { a : { b: 1, c: 2 } };

给定字符串“obj.ab”,我怎样才能得到它所指的对象,以便我可以改变它的值?即我希望能够做类似的事情

obj.a.b = 5;
obj.a.c = 10;

其中“obj.ab”和“obj.ac”是字符串(不是 obj 引用)。我遇到了这篇文章,在那里我可以获得点符号字符串所指的 obj 的值,但我需要的是一种可以获取对象本身的方法?

对象的嵌套可能比这更深。即也许

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
6个回答

要获得该值,请考虑:

function ref(obj, str) {
    str = str.split(".");
    for (var i = 0; i < str.length; i++)
        obj = obj[str[i]];
    return obj;
}

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = 'a.c.d'
ref(obj, str) // 3

或者以更奇特的方式,使用reduce

function ref(obj, str) {
    return str.split(".").reduce(function(o, x) { return o[x] }, obj);
}

在 javascript 中无法返回对对象成员的可分配引用,您必须使用如下函数:

function set(obj, str, val) {
    str = str.split(".");
    while (str.length > 1)
        obj = obj[str.shift()];
    return obj[str.shift()] = val;
}

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = 'a.c.d'
set(obj, str, 99)
console.log(obj.a.c.d) // 99

或者使用ref上面给出的来获取对包含对象的引用,然后对其应用[]运算符:

parts = str.split(/\.(?=[^.]+$)/)  // Split "foo.bar.baz" into ["foo.bar", "baz"]
ref(obj, parts[0])[parts[1]] = 99
现在很清楚了。我很困惑,因为set()你使用了与第一个不同的“数组遍历技术” ref(),我试图弄清楚为什么这是必要的 - 事实并非如此,但它使事情变得有趣。至于最后一个,正则表达式让我感到困惑,但我在代码中添加了注释。
2021-03-14 12:54:16
+1reduce起初没有看到您的示例。
2021-03-16 12:54:16
@Redsandro:嗯,你有什么问题吗?代码对我来说看起来很简单。
2021-03-18 12:54:16
如果您能详细说明set()以及split(/\.(?=[^.]+$)/)更多示例,我将不胜感激
2021-03-19 12:54:16
谢谢,第二部分是我一直在寻找的,似乎工作正常。
2021-03-26 12:54:16

类似于 thg435 的答案,但带有参数检查并支持其中一个祖先级别尚未定义或不是对象的嵌套级别。

setObjByString = function(obj, str, val) {
    var keys, key;
    //make sure str is a string with length
    if (!str || !str.length || Object.prototype.toString.call(str) !== "[object String]") {
        return false;
    }
    if (obj !== Object(obj)) {
        //if it's not an object, make it one
        obj = {};
    }
    keys = str.split(".");
    while (keys.length > 1) {
        key = keys.shift();
        if (obj !== Object(obj)) {
            //if it's not an object, make it one
            obj = {};
        }
        if (!(key in obj)) {
            //if obj doesn't contain the key, add it and set it to an empty object
            obj[key] = {};
        }
        obj = obj[key];
    }
    return obj[keys[0]] = val;
};

用法:

var obj;
setObjByString(obj, "a.b.c.d.e.f", "hello");
如果您能找到一种方法来编写未定义的属性而不覆盖同级预定义的属性,那就太好了
2021-03-22 12:54:16

如果这javascript在浏览器中运行,那么您可以像这样访问对象:

window['obj']['a']['b'] = 5

因此,鉴于字符串,"obj.a.b"您必须将其拆分为.

var s = "obj.a.b"
var e = s.split(".")
window[e[0]][e[1]][e[2]] = 5
如果它有更多的嵌套级别怎么办?
2021-03-16 12:54:16
是的。如果不知道有什么方法可以修改呢?
2021-03-28 12:54:16
嵌套层数未知吗?
2021-04-02 12:54:16
var obj = { a : { b: 1, c: 2 } };
walkObject(obj,"a.b"); // 1

function walkObject( obj, path ){
  var parts = path.split("."), i=0, part;
  while (obj && (part=parts[i++])) obj=obj[part];
  return obj;
}

或者,如果您喜欢简洁的代码:

function walkObject( o, path ){
  for (var a,p=path.split('.'),i=0; o&&(a=p[i++]); o=o[a]);
  return o;
}
@source.rar 这会返回链末尾的值,如第二行所示。如果该值是一个对象,那么您将返回一个对象(例如walkObject(obj,'a') // {b:1,c:2})。
2021-03-24 12:54:16
这不是让我得到点符号字符串的值吗?而不是我可以修改的对象本身?
2021-04-07 12:54:16

在 javascript 中无法返回对对象成员的可分配引用。您可以使用这样的一行代码通过点表示法为深层对象成员赋值。

new Function('_', 'val', '_.' + path + ' = val')(obj, value);

在你的情况下:

var obj = { a : { b: 1, c: 2 } };

new Function('_', 'val', '_.a.b' + ' = val')(obj, 5); // Now obj.a.b will be equal to 5