Handle undefined as an object

Is there a technique / framework, which creates and stores a new object into an undefined variable when it is handled as an object?

F.e. writing

some.thing = 7;

Gives an error describing, that undefined's ( some's ) property could not be set.

So now, we have to go back, and write

some = {};
some.thing = 7;

which looks almost unnecessary to me, since it is obvious, that I'd like to use some as an object.


It would be very comfortable this way:

hospitals.sectors.doctors = [];
hospitals.sectors.doctors[ 0 ].age = 32;

This looks way more efficient, and simple than

hospitals = {};
hospitals.sectors = {};
hospitals.sectors.doctors = [];
hospitals.sectors.doctors[ 0 ] = {};
hospitals.sectors.doctors[ 0 ].age = 32;

Upvotes: 0

Views: 124

Answers (3)

Pandacoder
Pandacoder

Reputation: 708

If you are trying to assign 7 to some.thing and some should not be declared at all beforehand, use Cory's suggestion of var some = { thing: 7 };.

If you are trying to assign 7 to some.thing and some might be declared/defined already (or even if it is declared, may or may not be set to undefined), use

(some = (some || {})).thing = 7;

or (a more readable solution, though not a one liner)

some = (some || {});
some.thing = 7;

The one caveat with my solution is that you might get undesired scoping on some if it isn't declared ahead of time. An example of where it would be undefined but still declared (and thus the scope would be what is expected):

function assignThing(some) {
    (some = (some || {})).thing = 7; /* one liner solution */
    return some;
}

var foo = assignThing(); /* the parameter 'some' is undefined, but declared */

var bar = assignThing({}); /* the parameter 'some' is defined
                            * (though empty) and declared */

(baz = (baz || {})).thing = 7; /* Unless you have this declared
                                        * elsewhere this *should* be the
                                        * global scope */

var foobar; /* declared, not defined */
(foobar = (foobar  || {})).thing = 7; /* now defined */

Edit: Created a namespace solution like what anddoutoi suggested. First example of usage (hospitals) uses the optional nature of the third parameter, which defaults to "undefined".

Second example (hospitals2) passes undefined.

Third example (hospitals3) passes another object (I happened to create it inline).

For the example you (the OP) provided, my hospitals example is the closest to an exact match. I don't know of a way to auto-magically create an object hierarchy besides using a canonical name string + a function.

function create(canonicalPropertyName, value, root) {
    root = (root || {});
    var names = canonicalPropertyName.split(".");
    var current = root;

    for (var i = 0; i < names.length; i++) {
        /* Ensure the property exists */
        current[names[i]] = (current[names[i]] || (i < names.length - 1 ? {} : []));

        /* We're recursing down the object tree */
        current = current[names[i]];
    }

    return root;
}

var hospitals = create("sectors.doctors", []);
hospitals.sectors.doctors[ 0 ] = {};
hospitals.sectors.doctors[ 0 ].age = 32;
console.log(hospitals);

var hospitals2 = create("sectors.doctors", [], undefined);
hospitals2.sectors.doctors[ 0 ] = {};
hospitals2.sectors.doctors[ 0 ].age = 32;
console.log(hospitals2);

var hospitals3 = create("sectors.doctors", [], { name: "City Hospital" });
hospitals3.sectors.doctors[ 0 ] = {};
hospitals3.sectors.doctors[ 0 ].age = 32;
console.log(hospitals3);

Upvotes: 1

anddoutoi
anddoutoi

Reputation: 10111

Many frameworks have a namespace() method/function that helps you achieve what you want.

Example:

Ext.ns('hospitals.sectors.doctors') = [];
var doctors = Ext.ns('hospitals.sectors.doctors');
doctors[0] = {
    age : 32
};

I myself don't like this pattern as it adds unnecessary dependencies and work.

Upvotes: 1

messerbill
messerbill

Reputation: 5639

you could write an own handler to do the job

function createObjectProperty(objNameString, objPropertyString, objValueString) {
window[objNameString] = {};
window[objNameString][objPropertyString] = objValueString;
return window[objNameString];}

var test = createObjectProperty("some", "thing", 7);
alert(test.thing);

the call would look like:

createObjectProperty("some", "thing", 7);

and it alerts "7".You also could check before creating the new object, if it exists. I would iterate over the object and gather all attributes, check for duplicate and append my new attribute + value if you need such functionality. Otherwise the new object will overwrite the old one. Hope this is what you are searching for

working fiddle (update):

https://jsfiddle.net/a922bopj/1/

Upvotes: 0

Related Questions