JuggernautDad
JuggernautDad

Reputation: 1145

Creative way to dynamically generate javascript objects

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?

Upvotes: 0

Views: 54

Answers (2)

epascarello
epascarello

Reputation: 207531

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)

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 370859

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);

Upvotes: 1

Related Questions