JavaScript 对象的动态深度设置

IT技术 javascript object
2021-02-20 08:04:34

给定对象属性路径的字符串,如何动态设置此属性。

鉴于此示例对象:

var obj = {
    a: {
        b: [ { c: 'Before' } ]
    }
};

它应该能够使用这样的辅助函数设置值:

setToValue(obj, 'After', 'a.b.0.c');

我用下面的代码试过了。但是如果变量不是引用,则 parent 是副本。

function setToValue(obj, value, path) {
    var arrPath = path.split('.'),
        parent = obj;

    for (var i = 0, max = arrPath.length; i < max; i++) {
        parent = parent[arrPath[i]];
    }

    parent = value;
}
3个回答

a) 简单的 ab[0].c = 'After' 有什么问题?

至于方法:

function setToValue(obj, value, path) {
    var i;
    path = path.split('.');
    for (i = 0; i < path.length - 1; i++)
        obj = obj[path[i]];

    obj[path[i]] = value;
}

这里是 JSFiddle:http : //jsfiddle.net/QycBz/24/

@PerLundberg 选择器可能是我在尝试代码时遗留下来的。可以安全删除。我更新了答案代码。
2021-04-19 08:04:34
谢谢我错过了“parent[path[path.length-1]] = value;”
2021-04-26 08:04:34
实际上这是 parent = value 的问题.. 因为你修改了一个局部变量而不是你持有对 .. 的引用的对象。
2021-05-04 08:04:34
Tigraine,这是一个老问题……但是在您的示例中,“选择器”变量到底在做什么?我正在尝试使用 CoffeeScript 重写它,所以这就是为什么我想知道... :)
2021-05-16 08:04:34
哇,这是一个很大的帮助 Tigraine。我正是需要这个,但我确实为数组添加了额外的语法类型,所以像“ab[2].c”这样的东西相当于“ab2.c”我分叉了你的JSFiddle,这里是jsfiddle.net/wxrzM /1
2021-05-16 08:04:34

这是一个完整的解决方案。

如果对象不存在,也会创建对象。

function setValue(obj, path, value) {
  var a = path.split('.')
  var o = obj
  while (a.length - 1) {
    var n = a.shift()
    if (!(n in o)) o[n] = {}
    o = o[n]
  }
  o[a[0]] = value
}

function getValue(obj, path) {
  path = path.replace(/\[(\w+)\]/g, '.$1')
  path = path.replace(/^\./, '')
  var a = path.split('.')
  var o = obj
  while (a.length) {
    var n = a.shift()
    if (!(n in o)) return
    o = o[n]
  }
  return o
}
这是否可以扩展,例如... var obj = {} setValue(obj, 'a.b.c', 123) setValue(obj, 'a.b.d', 456) // expected: { a: { b: { c: 123, d: 456 } } } // actual: { a: { b: { d: 456 } } } 目前,第二次调用 setValue 不会扩展对象
2021-04-25 08:04:34
非常好的代码,但它忽略了数组类型(例如:prop[0])
2021-04-26 08:04:34

FWIW,那些希望在 CoffeeScript 中使用相同方法的人可能会发现这些方法很方便——它是上述代码的直接移植。作为额外的奖励,它们确保路径中的所有对象都存在(如果不存在,getPropertyByPath 不会抛出异常,如果路径中的任何对象碰巧为空,则 set 方法将创建空对象)。

getPropertyByPath: (obj, path) ->
  path = path.split('.')
  parent = obj

  if path.length > 1
    parent = parent[path[i]] for i in [0..path.length - 2]

  parent?[path[path.length - 1]]

setPropertyByPath: (obj, path, value) ->
  path = path.split('.')
  parent = obj

  if path.length > 1
    parent = (parent[path[i]] ||= {}) for i in [0..path.length - 2]

  parent[path[path.length - 1]] = value