0

I was trying to create a function able to set a certain value of an object, having the "path" of the property:

reflectionSet = function(obj, propString, value) {
    var current = obj;
    var splitted = propString.split('.');
    splitted.forEach(function(k) {
        current = current[k];
    })
    current = value;
}
var test = {
    a: {
        s: 'asd',
        g: 'asasdasdd'
    }
};

reflectionSet(test, 'a.g', "otherValue");

and it should become:

{
    a: {
        s: 'asd',
        g: 'otherValue'
    }
}

Unfortunately this doesn't work at all.. Thanks

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
M4rk
  • 2,172
  • 5
  • 36
  • 70
  • That is because JavaScript is "pass-by-value". Which means that when you collect the variable g you wont be changing the value in the Object. Just the value you collected from the Object. [Here](http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value) is a more informative explanation – magnudae Oct 20 '14 at 14:05

2 Answers2

1

You can use split the properties based on . and then using Array.prototype.reduce, get to the inner most part of the Object and update it like this

function reflectionSet(obj, propString, value) {
    return propString.split(".").reduce(function(result, part, index, array) {
        if (index === array.length - 1) {
            result[part] = value;
            return obj;
        }
        return result[part];
    }, obj);
}

var test = {
    a: {
        s: 'asd',
        g: 'asasdasdd'
    }
};

console.log(reflectionSet(test, 'a.g', "otherValue"));

Output

{
    a: {
        s: 'asd',
        g: 'otherValue'
    }
}
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
1

This corrected version of your function should do it.

reflectionSet = function(obj, prop, value) {
    prop = prop.split('.');
    var root = obj, i;
    for(i=0; i<prop.length; i++) {
        if(typeof root[prop[i]] == 'undefined') root[prop[i]] = {};
        if(i === prop.length - 1) root[prop[i]] = value;
        root = root[prop[i]];
    }
    return obj;
};

Now:

var test = { a: { s: 'asd', g: 'asasdasdd' } };
reflectionSet(test, 'a.g', "otherValue");

Will return { a: { s: 'asd', g: 'otherValue' } }

techfoobar
  • 65,616
  • 14
  • 114
  • 135