How to automatically add properties to an object that is undefined?

Is there an easy way to automatically add properties to objects if they don't already exist?

Consider the following example:

var test = {}
test.hello.world = "Hello doesn't exist!"

This doesn't work because hello isn't defined.

The reason why I'm asking this is because I have some existing objects for which I don't know if they allready have hello or not. I actually have a lot of these objects in different parts of my code. It is very annoying to always check if hello exists and if it doesn't create a new object like:

var test = {}
if(test.hello === undefined) test.hello = {}
test.hello.world = "Hello World!"

Is there a way to automatically create an object like hello in this example?

I mean something like that in php:

$test = array();  
$test['hello']['world'] = "Hello world";   
var_dump($test);

Output:

array(1) {
  ["hello"] => array(1) {
    ["world"] => string(11) "Hello world"
  }
}

Ok it's an array but in js arrays it is the same problem as with objects.


Solution 1:

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.

Solution 2:

You can use the Logical nullish assignment (??=):

var test = {};
(test.hello ??= {}).world ??= "Hello doesn't exist!";

Solution 3:

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!

Solution 4:

You won't be able to do this without some sort of function, as JavaScript doesn't have a generic getter/setter method for objects (Python, for example, has __getattr__). Here's one way to do it:

function add_property(object, key, value) {
    var keys = key.split('.');

    while (keys.length > 1) {
        var k = keys.shift();

        if (!object.hasOwnProperty(k)) {
            object[k] = {};
        }

        object = object[k];
    }

    object[keys[0]] = value;
}

If you really want to, you could add it to the prototype of Object. You can call it like so:

> var o = {}
> add_property(o, 'foo.bar.baz', 12)
> o.foo.bar.baz
12