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.