Is there an easy way to automatically add properties to objects if they don\'t allready exist?
Consider the following example:
var test = {}
test.hel
Well you could extend the prototype of Object
with a function that return a property, but adds it first, if it doesn't exist:
Object.prototype.getOrCreate = function (prop) {
if (this[prop] === undefined) {
this[prop] = {};
}
return this[prop];
};
var obj = {};
obj.getOrCreate("foo").getOrCreate("bar").val = 1;
Here's a cool version with proxies:
const myUpsert = (input) => {
const handler = {
get: (obj, prop) => {
obj[prop] = obj[prop] || {};
return myUpsert(obj[prop]);
}
};
return new Proxy(input, handler);
};
And you use it like this:
myUpsert(test).hello.world = '42';
This will add all the missing properties as empty objects, and leave the existing ones untouched. It's really just a proxied version of the classic test.hello = test.hello || {}
, albeit much slower (See benchmark here.) But it's also much nicer to look at, especially if you'll be doing it more than one level deep. I wouldn't pick it for performance-heavy data crunching, but it's probably fast enough for a front-end state update (as in Redux).
Note that there's some implicit assumptions here:
test.hello
is a string, for example.These are pretty easily mitigated if you only use it in well-bounded contexts (like a reducer body) where there's little chance of accidentally returning the Proxy, and not much else you would want to do with the object.
var test = {}
test.hello.world = "Hello doesn't exist!"
This will throw an error obviously as you didn't defined the test.hello
Firstly you need to need define the hello key then inside you can assign any key. But if you want to create key if not exists then you can do following thing
test.hello = test.hello || {};
The above statement will create the test.hello object if not defined and if it is defined then it will assign the same value as it is previously
Now you can assign any new key inside the test.hello
test.hello.world = "Everything works perfect";
test.hello.world2 = 'With another key too, it works perfect';
var test = {}
if(!test.hasOwnProperty('hello')) {
test.hello = {};
}
test.hello.world = "Hello World!"
var test = {};
test.hello = test.hello || {};
test.hello.world = "Hello world!";
If test.hello
is undefined, it gets set to an empty object.
If test.hello
was previously defined, it stays unchanged.
var test = {
hello : {
foobar : "Hello foobar"
}
};
test.hello = test.hello || {};
test.hello.world = "Hello World";
console.log(test.hello.foobar); // this is still defined;
console.log(test.hello.world); // as is this.
New object
myObj = {};
recursive function
function addProps(obj, arr, val) {
if (typeof arr == 'string')
arr = arr.split(".");
obj[arr[0]] = obj[arr[0]] || {};
var tmpObj = obj[arr[0]];
if (arr.length > 1) {
arr.shift();
addProps(tmpObj, arr, val);
}
else
obj[arr[0]] = val;
return obj;
}
Call it with a dot notated string
addProps(myObj, 'sub1.sub2.propA', 1);
or with an array
addProps(myObj, ['sub1', 'sub2', 'propA'], 1);
and your object will look like this
myObj = {
"sub1": {
"sub2": {
"propA": 1
}
}
};
It works with non-empty objects too!