Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert string in dot notation to get the object reference [duplicate]

Consider this object in javascript,

var obj = { a : { b: 1, c: 2 } };

given the string "obj.a.b" how can I get the object this refers to, so that I may alter its value? i.e. I want to be able to do something like

obj.a.b = 5;
obj.a.c = 10;

where "obj.a.b" & "obj.a.c" are strings (not obj references). I came across this post where I can get the value the dot notation string is referring to obj but what I need is a way I can get at the object itself?

The nesting of the object may be even deeper than this. i.e. maybe

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
like image 628
source.rar Avatar asked Jun 07 '12 15:06

source.rar


2 Answers

To obtain the value, consider:

function ref(obj, str) {
    str = str.split(".");
    for (var i = 0; i < str.length; i++)
        obj = obj[str[i]];
    return obj;
}

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = 'a.c.d'
ref(obj, str) // 3

or in a more fancy way, using reduce:

function ref(obj, str) {
    return str.split(".").reduce(function(o, x) { return o[x] }, obj);
}

Returning an assignable reference to an object member is not possible in javascript, you'll have to use a function like the following:

function set(obj, str, val) {
    str = str.split(".");
    while (str.length > 1)
        obj = obj[str.shift()];
    return obj[str.shift()] = val;
}

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } }
str = 'a.c.d'
set(obj, str, 99)
console.log(obj.a.c.d) // 99

or use ref given above to obtain the reference to the containing object and then apply the [] operator to it:

parts = str.split(/\.(?=[^.]+$)/)  // Split "foo.bar.baz" into ["foo.bar", "baz"]
ref(obj, parts[0])[parts[1]] = 99
like image 103
georg Avatar answered Oct 14 '22 07:10

georg


Similar to thg435's answer, but with argument checks and supports nest levels where one of the ancestor levels isn't yet defined or isn't an object.

setObjByString = function(obj, str, val) {
    var keys, key;
    //make sure str is a string with length
    if (!str || !str.length || Object.prototype.toString.call(str) !== "[object String]") {
        return false;
    }
    if (obj !== Object(obj)) {
        //if it's not an object, make it one
        obj = {};
    }
    keys = str.split(".");
    while (keys.length > 1) {
        key = keys.shift();
        if (obj !== Object(obj)) {
            //if it's not an object, make it one
            obj = {};
        }
        if (!(key in obj)) {
            //if obj doesn't contain the key, add it and set it to an empty object
            obj[key] = {};
        }
        obj = obj[key];
    }
    return obj[keys[0]] = val;
};

Usage:

var obj;
setObjByString(obj, "a.b.c.d.e.f", "hello");
like image 9
dairystatedesigns Avatar answered Oct 14 '22 07:10

dairystatedesigns