Search code examples
javascriptobjectkey-value-observingkey-value-coding

Javascript object key value coding. Dynamically setting a nested value


I'm working on a little library that lets me do some basic key value coding with objects. Say I have the following object:

var data = { key1: "value1", key2: { nested1: 1, nested2: "wowza!" } };

And I have the following JavaScript function:

var setData = function(path, value) {
    eval("data." + path + "= value;");
};

And in use:

setData("key1", "updated value1"); // data.key1 == "updated value1"
setData("key2.nested1", 99); // data.key2.nested1 == 99

This works, however I would like to accomplish the above without using eval. Is this possible, or is eval the best way to go?

EDIT:

NOTE it can be assumed the value you're setting exists, at least for path depth - 1. I'm more concerned about setting the value of an existing object.


Solution

  • Recursion is what you need:

    function setData(key,val,obj) {
      if (!obj) obj = data; //outside (non-recursive) call, use "data" as our base object
      var ka = key.split(/\./); //split the key by the dots
      if (ka.length < 2) { 
        obj[ka[0]] = val; //only one part (no dots) in key, just set value
      } else {
        if (!obj[ka[0]]) obj[ka[0]] = {}; //create our "new" base obj if it doesn't exist
        obj = obj[ka.shift()]; //remove the new "base" obj from string array, and hold actual object for recursive call
        setData(ka.join("."),val,obj); //join the remaining parts back up with dots, and recursively set data on our new "base" obj
      }    
    }
    
    setData("key1", "updated value1"); // data.key1 == "updated value1"
    setData("key2.nested1", 99); // data.key2.nested1 == 99