0

I am working with a javascript object and need to set a value deep in the object structure.

Lets say:

a.b.c.d.e.f.g = "some value";

I don't know if all of these objects are created yet, so I end up doing:

a = a || {};
a.b = a.b || {};
a.b.c = a.b.c || {};
a.b.c.d = a.b.c.d || {};
a.b.c.d.e = a.b.c.d.e || {};
a.b.c.d.e.f = a.b.c.d.e.f || {};
a.b.c.d.e.f.g = "some value";

Surely there is a better way to do this right?

9
  • 1
    You could write a function that's called like set(a, ["b", "c", "d", ...], "some value"); Commented Jan 31, 2019 at 23:14
  • 1
    stackoverflow.com/questions/18936915/… Commented Jan 31, 2019 at 23:19
  • What do you mean by "I don't know if all of these objects are created yet"? Is the requirement to create the data structure or traverse an existing data structure? Commented Jan 31, 2019 at 23:21
  • it's a setting tree where a is the global list of settings. in my specific case, say a.b.c.d.x has already been set, then I would need to create the e and f object, and add the g property without screwing up anything above it. Commented Jan 31, 2019 at 23:29
  • Is the existing object data structure {"a":{"b":{"c":{"d":{}}}}}? Commented Jan 31, 2019 at 23:32

2 Answers 2

2

Easiest way is to use a string, split on the dots, and loop. When you loop you check to see if it exists, if it does, you use it. If it does not than you create a new object. You do that until you get to the end where you set the value.

const setValue = (obj, path, value) => {
  path.split('.') // split on the dots
    .reduce((o, k, i, a) => {
      o[k] = (i + 1 === a.length) // check if we are at last index
        ? value  // if last index use the value
        : (o[k] || {})  // else return object or set new one
      return o[k]  // return the current step in the object
    }, obj)  // start location
}

setValue(window, 'a.b.c.d.e.f.g', 'some value')
console.log(a.b.c.d.e.f.g)


var foo = { a : { b: {z : {} } } }
setValue(foo, 'a.b.c.d.e.f.g', 'another value')
console.log(foo)

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

1 Comment

really appreciate this. you just cleaned up like 1000 lines of code for me!
1

I'd use reduce to iterate over all props but the last, creating an object at the nested property if necessary, and returning the nested value. Then, on the last object, assign to the last property:

a = window.a || {};
const props = ['b', 'c', 'd', 'e', 'f'];
const lastProp = 'g';
const lastObj = props.reduce((a, prop) => {
  if (!a[prop]) a[prop] = {};
  return a[prop];
}, a);
lastObj[lastProp] = 'some value';
console.log(a);

Comments

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.