Saturday, March 2, 2019

Matchmaker, matchmaker: Getting a property from a matching path

As the use of JSON and JavaScript objects has increased, UI engineers have increasingly been tasked with locating a particular data point in an object. The typical response to this situation is to find a module that has the appropriate utility - usually lodash - and load that dependency.

As anyone who knows me can tell you, I dislike dependencies - a lot. Over my years of experience, dependencies have, on occasion, caused more problems than they've solved, and they have certainly caused more than a few sleepless nights.

Finding and retrieving a property, however, is a rather simple task as long as the path to the property can be specified in dot notation. Even more, this can be added to the JavaScript Object prototype easily and, as part of ES5, is supported by nearly all browsers...except Internet Explorer 8.

Here's the code you'll need - it's shown here as a method on a specific object, but I'll leave it up to you exactly how to implement it.

First, we'll create an object.

JavaScript
var myObject = {   situation: {     normal: {       afu: true     }   },   statuses: [     {       foobar: false, time: '1999-12-31T23:59:59'     },     {       foobar: true, time: '2000-01-01T03:00:00'     },     {       foobar: true, time: '2000-01-01T07:00:00'     },     {       foobar: true, time: '2000-01-01T11:00:00'     },     {       foobar: true, time: '2000-01-01T15:00:00'     },     {       foobar: true, time: '2000-01-01T19:00:00'     },     {       foobar: false, time: '2000-01-01T23:00:00'     }   ] }


Next we add our find method to it.

JavaScript find method
myObject.find = function (path, value) {   return path.split('.').reduce(function (ttl, val) {     var key = /(\w+)\[?(\d+)?\]?/.exec(val),       ref = ttl;     ref = ref && key[1] ? ref[key[1]] : ref;     ref = ref && key[2] ? ref[Number(key[2])] : ref;     return ref || value;   }, this); }


What this function is doing is relatively straightforward. It takes the path specified and splits it apart using the dots in the dot notation. It then loops through the array of path segments and shifts the reference point at each step, assuming the reference point actually holds a value. By adding the this keyword as the initial value of the reduce method, we eliminate the need for any external references. If the path is not found, and a default value is provided in the value parameter, the default value is returned, otherwise, undefined is returned.

With this find function, you can get a property value by specifying the path like so... myObject.find('situation.normal.afu'); // returns true. Any properties requested that are undefined, even if they are nested inside undefined properties, are returned as undefined. For example, with our object, myObject.find('situation.normal.nafu.ok') will return undefined without throwing a TypeError as would typically happen when 'ok' could not be read from the undefined 'nafu' property.

Hopefully this will simplify your code and reduce those dependencies.

Happy coding.

No comments:

Post a Comment