Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access nested objects via array of property names

Say I have an object like this (simplified):

var options = {
    boxes: {
        size: {
            x: 15,
            y: 18
        },
    shadow: {
        [...]
    }
};

And I have an array of names:

var names = ['boxes', 'size', 'x'];

What is an easy way to get/set a value inside the object according to the array, in this example it would be:

options.boxes.size.x = somevalue;

Any ideas?

like image 488
Lars Ebert Avatar asked Feb 15 '23 00:02

Lars Ebert


2 Answers

There's no easy, built-in method for doing this. You'd have to write your own method:

function getPath(obj, props) {
    for(var i = 0; i < props.length; i++) {
        if (props[i] in obj) {
            obj = obj[props[i]];
        } else {
            return; // not found
        }
    }

    return obj;
}

function setPath(obj, value, props) {
    for(var i = 0; i < props.length - 1; i++) {
        if (props[i] in obj) {
            obj = obj[props[i]];
        } else {
            return; // not found
        }
    }

    obj[props[i]] = value;
}

alert(getPath(options, names)); // 15
setPath(options, 25, names);  
alert(getPath(options, names)); // 25
like image 69
p.s.w.g Avatar answered Feb 17 '23 01:02

p.s.w.g


Just use a loop that iterates the names and grabs the next nested object for the current name. Either a falsey value or the end of the array should halt the loop.

var obj = options;
var i = 0;

while (obj && i < names.length)
    obj = obj[names[i++]];

Or simply use .reduce()

names.reduce(function(obj, name) {
    return obj && obj[name];
}, options);

And of course you can name and reuse the function if you prefer.

function toPropertyIn(obj, name) {
    return obj && obj[name];
}

names.reduce(toPropertyIn, options);

To make a getter/setter:

function nestedProp(obj, names, value) {
    if (arguments.length > 1)
        var setProp = names.pop();

    var res = names.reduce(function(obj, name) {
        return obj && obj[name];
    }, options);

    if (res && setProp !== undefined)
        res[setProp] = value;
    else
        return res;
}


nestedProp(options, names, "foo"); // to set

var val = nestedProp(options, names); // to get
like image 34
cookie monster Avatar answered Feb 17 '23 01:02

cookie monster