0

Let's say I have a dictionary like this (this is just example data):

obj = {
    name: 'John',
    properties: {
       age: 42,
       address: 'somewhere'
    }
}

What if I wanted to modify a value of any depth, specified by a variable?

For depth 1 it would be direct:

obj[what_to_modify] = new_value

but for depth > 1?

what_to_modify="properties.age"
obj[what_to_modify.split('.')] = new_value
// I KNOW, THIS DOESN'T WORK, IT JUST
// ILLUSTRATES WHAT I WANT TO ACHIEVE

My solution was to do a foor lop like this:

let levels = what_to_modify.split('.')
let it = obj
for(let k=0; k < levels.length; k++){
    let key = levels[k]
    if(k == levels.length -1){
        it[key] = new_value
    }else{
        it = it[key]
    }
}

This already works, but I wanted to know: Is there a less messy way to do it?


To be clear, I don't want to just read the value, I want to modify it, so Accessing nested JavaScript objects and arrays by string path and Access property via it's keyPath in Javascript? don't solve my problem


IMPORTANT

The accepted answer uses lodash, but actually I shouldn't include new dependencies in my project, so if there's any other way with vanilla JS, I will change the accepted answer to that.

4

2 Answers 2

2

You can use lodash. _.set sets a value by path and _.get returns a value by path. _.toPath converts a string to a path array.

const obj = {
    name: 'John',
    properties: {
       age: 42,
       address: 'somewhere'
    }
};

const propertiesAgePath = _.toPath('properties.age');
console.log(_.get(obj, propertiesAgePath));
_.set(obj, propertiesAgePath, 43);
console.log(_.get(obj, propertiesAgePath));
_.set(obj, _.toPath('properties.address'), 'new address');
console.log(obj);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

I'm going to upvote and accept, but actually I shouldn't include new dependencies to the project I'm working on, so if there's any other answer that can do that for me without lodash, I will have to change it. Thanks anyway
@Miguel That's very sad that so many people insist in reinventing the wheel. That's a solved problem and lodash has so many helpful tools that I add it to most projects I'm working in. It's great for deep clones, creating ranges, complex object modifications, ...
1

You can also carefully use eval to accomplish this.

let new_value = 9

obj = {
    name: 'John',
    properties: {
       age: 42,
       address: 'somewhere'
    }
}

what_to_modify="properties.age"

eval("obj."+what_to_modify+"= new_value")

console.log(obj)

4 Comments

Please read Never use eval()!
I'm not going to include eval in my code, but thank you for taking your time to answer.
eval is dangerous depending on what you put in there. Understand your desire to not use it.
It's not only dangerous but also slow. It can easily be replaced with functions with better performance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.