0

I have an object similar to the following, although nested a few letters deeper:

var foo = {
    a:{
        a:{},
        b:{}
    },
    b:{
        a:{},
        b:{}
    }
}

Given an array of arbitrary length containing 'a's and 'b's, for example ['b','a'], I want to modify the object key mapped by the array letters. So with the array I just gave, I want to modify foo['b']['a'], or foo.b.a.

I can think of an easy way to get the target value, using something like the following:

var context = foo
for(letter in array){
 context = context[letter]
}
return context

The issue with this is that if I tried to modify the final value of context, it won't modify the original object, which is what I want. Ideally if I had some method of creating pointers this would be simple, but I don't think javascript has them.

So is there any way to do this efficiently?

Ari
  • 3,489
  • 5
  • 26
  • 47
  • `foo[letter] = 'modified value'` instead, then. – Marc B Feb 15 '14 at 01:32
  • Javascript arrays and objects are always passed as references, they're not copied. So the final value of `context` should be an object that you can modify. – Barmar Feb 15 '14 at 01:34
  • 1
    Can you show an example of on operation on your original data and what the result should look like? It's not clear. – Pointy Feb 15 '14 at 01:34
  • @Barmar I can modify context, yes; but it doesn't contain a reference to the same location in foo, so foo will stay the same. – Ari Feb 15 '14 at 01:36
  • If you do `context.bar = 3`, and then look at `foo`, you should see `a: { bar: 3 }` at the appropriate place. – Barmar Feb 15 '14 at 01:37
  • @Barmar I'll try that and let you know if it works. – Ari Feb 15 '14 at 01:38
  • @Barmar You can try running this code in your js console: https://gist.github.com/anonymous/3ce714ae6292cc945cb3 It does not modify foo. – Ari Feb 15 '14 at 01:44
  • You have to assign to `context.somthing`, not `context`. – Barmar Feb 15 '14 at 01:45
  • @Barmar Ok, that worked. It seems like a strange behavior though. Why does assigning directly to context lose the reference? – Ari Feb 15 '14 at 01:48
  • The variable is essentially a pointer. If you assign to the variable, you're changing it to point to somewhere else. When you assign to the property, you're indirecting through the pointer to the object. – Barmar Feb 15 '14 at 01:50
  • See here http://stackoverflow.com/questions/18891939/javascript-retrieve-object-property-path/18892019#18892019 – elclanrs Feb 15 '14 at 01:53
  • @FelixKling As is suggested in my question, it is trivial to access the nested keys. The issue I was having was how to modify said key in the original object, which is not a duplicate. Regardless, Barmar provided the answer I needed using references. – Ari Feb 15 '14 at 02:39
  • @Ari: Oh, so you wanted to assign a value to the nested keys? Then it's probably a duplicate of http://stackoverflow.com/q/13719593/218196. – Felix Kling Feb 15 '14 at 03:26

1 Answers1

1

a reusable function makes it easy to resolve arbitrary depths:

function resolve(path, object) {
    var tob = object;
    path.map(function(a) {
        return (tob = tob[a]) || tob;
    });
    return tob;
}


var foo = {
    a:{
        a:{},
        b:{}
    },
    b:{
        a:{},
        b:{}
    }
};

var path= ['b','a'] ;


// resolve path and add a new property:
resolve(path, foo).c=123;
console.log(foo) /* shows:
{
    "a": {
        "a": {},
        "b": {}
    },
    "b": {
        "a": {
            "c": 123
        },
        "b": {}
    }
} */

and thus we can see that there is a now a property foo.b.a.c as expected.

dandavis
  • 16,370
  • 5
  • 40
  • 36