0

I would like to control values in an object using a string as the path to the value to change. For example, I have :

let object = { v: 12, o: { v: 15 }}

If I provide path: 'object.v' and value: 16, object becomes :

{ v: 16, o: { v: 15 }}

If I provide path: 'object.o.v' and value: 8, object becomes :

{ v: 16, o: { v: 8 }}

The path can also point to an object, for instance 'object.o'.
If the path point to a non-existing variable, the function will create it and also create the parents, for instance 'object.o.o2.o3'

Actually I know how I can do that using a for loop and just creating the structure and changing the value on the last crumb but I'd like to know if Javascript provides with simple function for doing that.

Or here is how I would implement that using for loop

let object = { v: 12, o: { v: 15 }}

function update (path, value) {

  const crumbs = path.split('.');
  let currentCrumb = object;

  let i;
  for (i = 1, count = crumbs.length; i < count - 1; ++i) {
    if (currentCrumb[crumbs[i]] === undefined) {
      currentCrumb[crumbs[i]] = {};
    }
    currentCrumb = currentCrumb[crumbs[i]];
  }

  currentCrumb[crumbs[i]] = value;
}

// usage
update('object.o.v', 51);
// object is now { v: 12, o: { v: 51 }}

Don't JavaScript provides some useful function to update objects using paths or something ? Or what would be your way of resolving that ?

Thanks

UPDATE :
Some tells me to use eval, the problem is the value can be an object as I said. So writing eval(path + '=' + value) is invalid, I could use JSON.stringify(value) when the value is an object but then the reference is lost, that means if value changes elsewhere, the eval'ed path is not affected by this change. Any other suggestions ?

4
  • I think is better send object like param, then the second param will be the path, is more dynamic... update(object, 'o.v', 51); Commented Sep 22, 2017 at 15:16
  • @kip yes sure, I was just providing an example, it's not really the context I try to implement here Commented Sep 22, 2017 at 15:18
  • 1
    Use eval function Commented Sep 22, 2017 at 15:23
  • @Ammar yeah, but check my update please. Commented Sep 22, 2017 at 15:31

1 Answer 1

2

This can be done with the lodash library, they call this a "property path array".

> _ = require('lodash')
> object = { v: 12, o: { v: 15 }}
{ v: 12, o: { v: 15 } }
> _.at(object, ['o.v'])
[ 15 ]
> _.set(object, 'o.v', 16)
{ v: 12, o: { v: 16 } }
> _.set(object, 'o.o2.o3', 'foo')
{ v: 12, o: { v: 16, o2: { o3: 'foo' } } }
Sign up to request clarification or add additional context in comments.

1 Comment

thanks but I think I will go with the chunk I provided, because I'm trying to build a custom element so I don't want to force the users to load extra libraries.

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.