2

Is there an easy way to extend a JavaScript object by passing a string and a value?

Basically I need something like this:

myObject = {}

var extendObj = function(obj, path, value){
}

var path = "a.b.c", value = "ciao";
extendObj(myObject, path, value);


console.log(myObject.a.b.c) //will print "ciao"
Marco C
  • 3,101
  • 3
  • 30
  • 49
  • But then what will be `a` and `b` – Derek 朕會功夫 Apr 24 '13 at 01:59
  • If they are undefined an empty object. If they are defined extend it. – Marco C Apr 24 '13 at 02:03
  • 1
    It IS ambiguous, but I am guessing the assumption would be - if it does not exist already, create it as an object. I think the real ambiguity here lies in this: what should it do if b already exists, but is a number and therefore cannot have a string as member. – Chris O'Kelly Apr 24 '13 at 02:04
  • From ["javascript dynamic object path"](http://stackoverflow.com/search?q=javascript+dynamic+object+path), see http://stackoverflow.com/questions/2061325/javascript-object-key-value-coding-dynamically-setting-a-nested-value , http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key , http://stackoverflow.com/questions/13719593/javascript-how-to-set-object-property-given-its-string-name , etc. – user2246674 Apr 24 '13 at 02:06
  • 1
    @Chris "what should it do if b already exists, but is a number and therefore cannot have a string as member" this case will not appen – Marco C Apr 24 '13 at 02:09

1 Answers1

3
myObject = {};

var extendObj = function (obj, path, value) {
    var levels = path.split("."),
        i = 0;

    function createLevel(child) {
        var name = levels[i++];
        if(typeof child[name] !== "undefined" && child[name] !== null) {
            if(typeof child[name] !== "object" && typeof child[name] !== "function") {
                console.warn("Rewriting " + name);
                child[name] = {};
            }
        } else {
            child[name] = {};
        }
        if(i == levels.length) {
            child[name] = value;
        } else {
            createLevel(child[name]);
        }
    }
    createLevel(obj);
    return obj;
}

var path = "a.b.c",
    value = "ciao";
extendObj(myObject, path, value);


console.log(myObject.a.b.c) //will print "ciao"

http://jsfiddle.net/DerekL/AKB4Q/

enter image description here

You can see in the console that it creates the path according to path you entered.

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • @MarcoCalì - I have tweaked the code a little bit so that it will: 1. preserve values that already exist in the object and, 2. rewrite the property if the type of the existing value is not an object. – Derek 朕會功夫 Apr 24 '13 at 02:20
  • 1
    +1 Clever use of recursion! Just a few details: you don't have to pass value when you recurse (you never use arguments[1] indeed); you don't have to rewrite functions, as they can have properties; it will fail if a or b is null (`typeof null === "object"`). – bfavaretto Apr 24 '13 at 02:55