Подтвердить что ты не робот

Динамическая глубокая настройка для объекта JavaScript

С учетом строки для пути свойств объекта, как я могу установить это свойство динамически.

Учитывая этот образец объекта:

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

Он должен иметь возможность установить значение с помощью вспомогательной функции, например:

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

Я попробовал его со следующим кодом. Но родитель является копией, если переменная не является ссылкой.

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;
}
4b9b3361

Ответ 1

a) Что не так с простым a.b [0].c = 'После'?

Что касается метода:

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/

Ответ 2

Вот полное решение.

Также создает объекты, если они не существуют.

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
}

Ответ 3

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