2

This question achieves kinda the opposite of what I'm trying to do. Basically, I have this object:

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

What I need to do is set the value of c given the string 'b.c'. Unfortunately, I can't do this:

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

As far as I can tell, the question above doesn't get me anywhere close as it just copies the values of the object properties so they can be read. It doesn't help me set the values of the object properties, however. Here's what I have so far:

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

for (var i = 0; i < key.length; i++) {
    // do something
}
Community
  • 1
  • 1
Big McLargeHuge
  • 14,841
  • 10
  • 80
  • 108
  • Do you know for sure that the string will always be valid and provide a path, denoted by `.`? If so, split the string by `.`, then loop through and index the object with every item – Ian Jun 13 '13 at 03:49
  • 4
    Here's more or less what I got: http://jsfiddle.net/RTtMQ/ . I don't know how universal it can be used – Ian Jun 13 '13 at 03:55
  • Mind posting it as the answer, with explanation? I'm having a hard time understanding what it's doing. – Big McLargeHuge Jun 13 '13 at 04:07

3 Answers3

3

Here's a functional way, is this what you need? It doesn't use the particular a[string] syntax but a function where you can pass the object string and the value to set:

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"
elclanrs
  • 92,861
  • 21
  • 134
  • 171
1

You have to intercept the last iteration of the loop, and from there assign instead of redefining your temp variable.

I adapted the answer to the question you linked to assign the value 2 to 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/


This is pretty much what @Ian is doing in his jsfiddle. Intead of an if, he loops one step less, then deals with the assignment after the loop.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
0

For the record, I eventually figured out another way to do this:

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

Call it like this:

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

var whatever = 'b.c';

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

setProperty(a, props, 'Bar');
Big McLargeHuge
  • 14,841
  • 10
  • 80
  • 108