1

Coming off my previous question (which was about getting the property), I need to set the value of a nested object member using a dynamic property name.

const settings = {
  service: {
    username: 'foo',
    password: 'bar'
  }
};

const settingName = 'service.username';
const newValue = 'baz';

settings[settingName] = newValue ; // doesn't work
console.log(settings.service.username); // foo

The only way I can think of is to use eval:

eval(`settings.${settingName} = "${newValue}"`);

const settings = {
  service: {
    username: 'foo',
    password: 'bar'
  }
}

const settingName = 'service.username';

const newValue = 'baz';

eval(`settings.${settingName} = "${newValue}"`); // works, but bad

console.log(settings.service.username);

But this has problems (for example, the example above assumes the new value is a string). Is there a way to assign a property of a nested object whose name is not known without using eval?

Community
  • 1
  • 1
Marks Polakovs
  • 510
  • 5
  • 18
  • Can't you just use a slightly modified version of the getter function from your other question? – nnnnnn Sep 18 '16 at 11:17

2 Answers2

1

You can do it like below,

var settings = {service: {username: 'TEST', password: ''}}
var key = "service.username";

function setValue(obj, keys, val){
  keys.split(".").forEach(function(itm, i, arr){
    if (i == arr.length - 1) obj[itm] = val;
    else obj = obj[itm];
  });
}

setValue(settings, key, "hello");
console.log(settings.service.username); //"hello"
Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
0

Also a follow-up on my previous answer: yes.

We can use the Function constructor to create and run code that will set the property by its name, as if it were done with a regular dot property access.

const settings = {
  service: {
    username: 'foo',
    password: 'bar'
  }
};

const settingName = 'service.username';
const newValue = 'baz';

Function('settings', 'value', 'settings.' + settingName + ' = value')(settings, newValue);

console.log(settings.service.username); // "baz"
GOTO 0
  • 42,323
  • 22
  • 125
  • 158
  • 1
    How is this different from my `eval` example above? (I mean, how is this better than eval?) – Marks Polakovs Sep 18 '16 at 11:22
  • @marksomnian My code works for values of any type (not just strings). If you're unclear about the differences between `eval` and the `Function` constructor, you may want to have a look here: http://stackoverflow.com/questions/4599857/are-eval-and-new-function-the-same-thing – GOTO 0 Sep 18 '16 at 11:24