0

How can I reach into a object using an array and set a value - preferably without using eval, doing something like object[eval(["key", "deepkey"].split("")) = "newvalue"?

Doing it manually, I would just do object.key.deepkey = "newvalue", but again, I need to do this using an array to reach into the right property.

The object for reference:

object = {
  key: {
    deepKey: "value"
  }
}
2
  • Could you clarify what you are trying to do? Commented Oct 14, 2012 at 12:24
  • Please give your working eval version. Commented Oct 14, 2012 at 12:25

4 Answers 4

2

You can use a recursive function to step through each level of the array (or object) like so:

function val(array, indices) {
    if(indices.length > 1) {
        var idx = indices.shift();
        return val(array[idx], indices);
    }
    else {
        return array[indices.shift()];
    }
}

var obj = { a: { b: 'c' } };

//result is 'c'
var result = val(obj, ['a', 'b']);

If you want to get an object reference, simply specify the second arg only up to that:

var obj = {
    a: {
        b: {
            c: 'foo'
        }
    }
};

var ref = val(obj, ['a', 'b']);

//ref is now obj.a.b, so you can do something like...
ref.x = 'bar';

console.dir(ref); //outputs something like { c: 'foo', x: 'bar' }
Sign up to request clarification or add additional context in comments.

2 Comments

Thats nice, but how do I set the value of b in your example?
@Industrial I'm sorry I didn't quite understand what you mean by that... obj.a.b = foo? Or do you actually want to use this function to get a reference to b instead of returning the value from it?
2

You can write array type syntax as. jsfiddle

object = {
  key: {
    deepKey: "value"
  }
}

object['key']['deepkey']='newvalue'

if you have keys in array you can do this

var keys = ['key','deepkey'];
var obj = object;
for(var k =0; k <keys.length-1; k++){
   obj= obj[keys[k]];
}
obj[keys[k]] = 'newvalue'

2 Comments

Sure, but this would only work with a two-level object where I know that the first level is named key. I need to be able to set nested values on unknown level.
You can iterate through object using for in and set the values.
0

You can take the function from this question and rework it to access properties of an object.

http://jsfiddle.net/jbabey/Mu4rP/

var getPropByName = function (propName, context) {
    var namespaces = propName.split('.');

    for(var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }

    return context;
};

var myObject = {
    someKey: {
        deepKey: "value"
    }
};

myObject.someKey.deepKey; // "value"
getPropByName('someKey.deepKey', myObject); "value"

Comments

0

An alternative could be using Array.map this way:

function deepkey(obj,keys,set){
  var i=1
     ,kys = keys.split('.')
     ,exist = kys.map( function(k){
          var prev = this[i-1], isobj = prev.constructor === Object;
          this.push( isobj && k in prev ? prev[k] : prev);
          return (i++,this[i-1]);},
          [obj]
        )
     ,x = exist[exist.length-2];
  if (x && x.constructor === Object && set){
    x[kys[kys.length-1]] = set;
  }
  return x[kys.pop()] || null;
} 
// usage
var obj = { a:{ b:{ c:1, cc:{ d:{ e:{ a:1,b:2,c:3 } } } } } };
// assign [1,2,3,4,5] to obj.a.b.cc.d.e.b
console.log(deepkey(obj,'a.b.cc.d.e.b',[1,2,3,4,5])); //=> [1,2,3,4,5]
// get obj.a.b.cc.d.e.b[2]
console.log(deepkey(obj,'a.b.cc.d.e.b')[2]); //=> 3
// get non existing path obj.a.b.c.d.e.b
console.log(deepkey(obj,'a.b.c.d.e.b')); //=> null

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.