Get and Set Nested Objects with JavaScript

By  on  

Back when JavaScript frameworks like MooTools and jQuery ruled the land we all wrote tutorials which were framed more toward the given framework instead of vanilla JavaScript.  Sad but true.  These days I avoid framework-oriented posts since Node.js has taken over the world and JavaScript toolkits come and go.

One very useful post I wrote and still love is Create and Retrieve Nested Objects with MooTools.  In that post I showed you how you can easily get and set nested objects, since doing existence checks down the object chain in a manual way is ... ugly.  Let's tear this functionality out of its MooTools orientation so you can take it with you wherever you go!

The JavaScript

We'll use a simple immediately-executing function to wrap the underlying "worker" function and return an object with properties for getting, setting, and checking existence:

var Objectifier = (function() {

	// Utility method to get and set objects that may or may not exist
	var objectifier = function(splits, create, context) {
		var result = context || window;
		for(var i = 0, s; result && (s = splits[i]); i++) {
			result = (s in result ? result[s] : (create ? result[s] = {} : undefined));
		}
		return result;
	};

	return {
		// Creates an object if it doesn't already exist
		set: function(name, value, context) {
			var splits = name.split('.'), s = splits.pop(), result = objectifier(splits, true, context);
			return result && s ? (result[s] = value) : undefined;
		},
		get: function(name, create, context) {
			return objectifier(name.split('.'), create, context);
		},
		exists: function(name, context) {
			return this.get(name, false, context) !== undefined;
		}
	};

})();

So how would you use this set of functions?  Here are some sample usage examples:

// Creates my.namespace.MyClass
Objectifier.set('my.namespace.MyClass', {
	name: 'David'
});
// my.namespace.MyClass.name = 'David'

// Creates some.existing.objecto.my.namespace.MyClass
Objectifier.set('my.namespace.MyClass', {
	name: 'David'
}, some.existing.objecto); // Has to be an existing object

// Get an object
Objectifier.get('my.namespace.MyClassToo');

// Try to find an object, create it if it doesn't exist
Objectifier.get('my.namespace.MyClassThree', true);

// Check for existence
Objectifier.exists('my.namespace.MyClassToo'); // returns TRUE or FALSE

Notice I didn't extend the Object prototype; you could but we've moved on from that practice.

I use these functions on just about every project I work on.  I find them very useful when dealing with APIs, as you can never assume an object chain exists.  I wish I had included this code within my 7 Essential JavaScript Functions post!

Recent Features

  • By
    An Interview with Eric Meyer

    Your early CSS books were instrumental in pushing my love for front end technologies. What was it about CSS that you fell in love with and drove you to write about it? At first blush, it was the simplicity of it as compared to the table-and-spacer...

  • By
    Create a CSS Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

Incredible Demos

  • By
    MooTools, mediaboxAdvanced, and Mexico

    The lightbox is probably one of my favorite parts of the Web 2.0 revolution. No more having to open new windows (which can bog down your computer quite a bit) to see a larger image, video, etc. Instead, the item loads right into the...

  • By
    MooTools Fun with Fx.Shake

    Adding movement to your website is a great way to attract attention to specific elements that you want users to notice. Of course you could use Flash or an animated GIF to achieve the movement effect but graphics can be difficult to maintain. Enter...

Discussion

  1. Rick

    I’ve recently published a PHP Class that does much the same thing but in PHP (with a few extra magic functions) and designed for nested arrays and objects…

    Nest

    $nest = new Nest\Nest();
    $nest->foo__bar = "baz";
    var_dump($nest->doesnt__exist); // null
    var_dump($nest->doesnt__exist("my default")); // "my default"
    
  2. voon ming hann

    lodash has this, it’s _.set(obj, 'a.b.c', 'new value')

  3. Bill

    I can’t get this to work, the “exists” part always returns false for me, even though I’ve double checked everything is correct in my code. Are you sure this function works as you describe? In particular checking if an object exists? I would like to use it, but not if it’s broken.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!