Home > Enterprise >  Is there a shorter way to write this code, assign a value to a sub object?
Is there a shorter way to write this code, assign a value to a sub object?

Time:09-27

I'm working with nodeJs and I would like to assign a sub value to an object without to know if the «three» exist.

E.g : I would like to assign True to «global.proc.trackingMarketExport.started» without check if :

  • proc exist in global
  • trackingMarketExport exist in global.proc
  • ....

Actually I'm writing this :

!global?.proc && ( global.proc = {})
!global.proc?.trackingMarketExport && ( global.proc.trackingMarketExport = { started: false })

For sample :

global?.proc?.trackingMarketExport?.started = true;

Thanks in advance for your help

CodePudding user response:

Not sure if this is short enough, but...

var started = ((global.proc) && (global.proc.trackingMarketExport))? true : false;
if (started) { global.proc.trackingMarketExport = started; }

CodePudding user response:

You could write something that walks the tree and sets an object if it does not exist. Many ways to write it.

const setObj = (obj, path, value) => {
  const parts = path.split('.');
  const lastKey = parts.pop();
  const lastObj = parts.reduce((acc, key) => {
    acc[key] = acc[key] || {};
    return acc[key];
  }, obj);
  lastObj[lastKey] = value;
}

const path = 'proc.trackingMarketExport.started';
const value = false;

const x = {};
setObj(x, path, value);
console.log(x);

const y = {
  "proc": {
    "foo" : "baz",
    "trackingMarketExport": {
      "funky": {
        "boo" : "bah"
      }
    }
  }
};
setObj(y, path, value);
console.log(y);

while loop

const setObj = (obj, path, value) => {
  const parts = path.split('.');
  let key;
  let walker = obj;
  while (key = parts.shift()) {
    walker[key] = parts.length ? (walker[key] || {}) : value;
    walker = walker[key];
  }
}

const path = 'proc.trackingMarketExport.started';
const value = false;

const x = {};
setObj(x, path, value);
console.log(x);

const y = {
  "proc": {
    "foo" : "baz",
    "trackingMarketExport": {
      "funky": {
        "boo" : "bah"
      }
    }
  }
};
setObj(y, path, value);
console.log(y);

CodePudding user response:

Edit: Perhaps you're asking how to ensure that the target object exists and that its started property is set to true?

If that's the case you can use the logical nullish assignment operator (??=):

(((global ??= {}).proc ??= {}).trackingMarketExport ??= {}).started = true;

let global = undefined;

(((global ??= {}).proc ??= {}).trackingMarketExport ??= {}).started = true;

console.log(global);


You can use this syntax to assign it to the target object (if it exists) or to an anonymous, ephemeral object that will be garbage collected (if it doesn't):

(global?.proc?.trackingMarketExport ?? {}).started = true;

Here's a code snippet you can re-run repeatedly to see randomized results. Note that in both cases no error occurs:

let global = undefined;

if (Math.random() < 0.5) {
  global = {
    proc: {
      trackingMarketExport: {},
    },
  };
}

(global?.proc?.trackingMarketExport ?? {}).started = true;

console.log(global);

CodePudding user response:

Check out the Object.assign() method, which copies all properties to a target object and overrides it.

Object.assign(global, {
    proc: {
        trackingMarketExport: {
            started: true
        }
    }
})

Then you can just put it in one line:

var globalDemo = {
 otherProperties: {
     a: 1,
     b: 2
 }
}

Object.assign(globalDemo, { proc: { trackingMarketExport: { started: true }}});

console.log(globalDemo);
console.log(globalDemo.proc.trackingMarketExport.started);

However, as mentioned in the comments, this technique will only work in your specific given scenario, because the other properties inside proc and trackingMarketExport will also be overridden and therefore deleted.

  • Related