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
    Welcome to My New Office

    My first professional web development was at a small print shop where I sat in a windowless cubical all day. I suffered that boxed in environment for almost five years before I was able to find a remote job where I worked from home. The first...

  • By
    5 Awesome New Mozilla Technologies You’ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • By
    Flexbox Equal Height Columns

    Flexbox was supposed to be the pot of gold at the long, long rainbow of insufficient CSS layout techniques.  And the only disappointment I've experienced with flexbox is that browser vendors took so long to implement it.  I can't also claim to have pushed flexbox's limits, but...

  • By
    CSS Fixed Position Background Image

    Backgrounds have become an integral part of creating a web 2.0-esque website since gradients have become all the rage. If you think gradient backgrounds are too cliche, maybe a fixed position background would work for you? It does provide a neat inherent effect by...

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!