Установите свойство JSON с полной строкой

Этот вопрос достигает своего рода противоположности тому, что я пытаюсь сделать . В принципе, у меня есть этот объект:

var a = {
    b: {
        c: 'Foo'
    }
}

Что мне нужно сделать, так это установить значение c с учетом строки 'b.c'. К сожалению, я не могу сделать это:

a['b.c'] = 'Bar'

Насколько я могу судить, приведенный выше вопрос не приближает меня к чему-либо, поскольку он просто копирует значения свойств объекта, чтобы их можно было прочитать. Однако это не помогает мне устанавливать значения свойств объекта. Вот что у меня есть до сих пор:

var key = 'b.c'.split('.');

for (var i = 0; i < key.length; i++) {
    // do something
}

person Big McLargeHuge    schedule 13.06.2013    source источник
comment
Вы точно знаете, что строка всегда будет действительна и будет указывать путь, обозначенный .? Если это так, разделите строку на ., затем выполните цикл и индексируйте объект с каждым элементом.   -  person Ian    schedule 13.06.2013
comment
Вот более или менее то, что я получил: jsfiddle.net/RTtMQ . Я не знаю, насколько универсально это может быть использовано   -  person Ian    schedule 13.06.2013
comment
Не могли бы опубликовать это как ответ с объяснением? Мне трудно понять, что он делает.   -  person Big McLargeHuge    schedule 13.06.2013


Ответы (3)


Вы должны перехватить последнюю итерацию цикла и оттуда назначить вместо переопределения вашей временной переменной.

Я адаптировал ответ на вопрос, который вы связали, чтобы присвоить значение 2 a.b.c:

var a = {
  "b" : {
    "c" : 1
  }
}

var n = "b.c".split(".");
var x = a;
for(var i = 0; i < n.length; i++){
    if(i == n.length-1) {
        x[n[i]] = 2;
    } else {
        x = x[n[i]];
    }
}

http://jsfiddle.net/Fuhbb/


Это в значительной степени то, что @Ian делает в своем jsfiddle. Вместо if он выполняет цикл на один шаг меньше, а затем выполняет задание после цикла.

person bfavaretto    schedule 13.06.2013

Вот функциональный способ, это то, что вам нужно? Он использует не особый синтаксис a[string], а функцию, в которой вы можете передать строку объекта и значение для установки:

var obj = { foo: { bar: { lol: { lulz: 69 } } } };

function setProp(obj, prop, value) {
  var props = prop.split('.');
  return [obj].concat(props).reduce(function(a,b,i) {
    return i == props.length ? a[b] = value : a[b];
  });
}

setProp(obj, 'foo.bar.lol.lulz', 'hello world');

console.log(obj.foo.bar.lol.lulz); //=> "hello world"
person elclanrs    schedule 13.06.2013
comment
Хороший! И его можно легко настроить, чтобы он действовал как геттер, если значение не передается. - person bfavaretto; 13.06.2013

Для справки, я в конце концов придумал другой способ сделать это:

function setProperty(obj, props, val) {
    if (obj[props[0]] instanceof Object) {
        setProperty(obj[props[0]], props.slice(1, props.length), val);

        return;
    }

    obj[props[0]] = val;
}

Назовите это так:

a = {
    b: {
        c: 'Foo'
    }
};

var whatever = 'b.c';

var props = whatever.split('.');

setProperty(a, props, 'Bar');
person Big McLargeHuge    schedule 20.06.2013