DEV Community

Cover image for How to navigate complex objects in 1 line of js
Luca Gesmundo
Luca Gesmundo

Posted on

How to navigate complex objects in 1 line of js

Today I want to share a pretty cool one-liner that makes your navigation in complex objects a breeze.. In just one minute 🤯
Let's get straight to the point.


const navigator = (obj, path) => path.reduce((a, b) => a && a[b], obj);

Given an object and an array representing all the properties (in descending order) from parent to the target property, we can navigate to our target value.

The native Array.prototype.reduce method is helping us achieve just that.

You can get familiar with reduce here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

We are providing our complex object as the initial value to our reduce method. And we are also providing a function that handles the reduction of our initial value.

We can then use the navigator function like that:

// Test object
const test = {
  a: {
    b: {
      c: 'test',
    },
  },
};

navigator(test, ['a', 'b', 'c']); // 'test'

The basic flow

Let's break it down what's happening in here:

➡ On first execution a, the accumulator, will have value obj.
➡ If a[b] exists, on the next iteration, a will be equal to a[b].
➡ If a[b] is undefined, then a is our target value.

NOTE: Using the logical AND operator (&&), if both values are truthy, the second value will be returned.

Looking for a more convenient syntax

The array notation to describe a nested path is not so handy.
But fortunately, we can upgrade it to a more convenient dot notation syntax pretty easily.

// Splitting dot notation path => resulting in the array we need.
const navigator = (obj, path) => path.split('.').reduce((a, b) => a && a[b], obj);

Then we can finally use it like the following:


const test = {
  a: {
    b: {
      c: 'test',
    },
  },
};

// 🎉🎉🎉🎉
navigator(test, 'a.b.c'); // 'test'

We have now the power to navigate very deeply nested properties with only one line of js 🎉🎉

Top comments (1)

Collapse
 
karataev profile image
Eugene Karataev

Great one-line helper!
I think the post misses the the motivation behind navigator function. Indeed, why use navigator(test, 'a.b.c') instead of short test.a.b.c?
This navigator function helps to avoid runtime errors when trying to read properties from null or undefined.
test.z.x will throw, but navigator(test, 'z.x') will return undefined.
This is such a common problem, so TC39 proposes optional chaining with syntax test?.a?.b?.c which is currently in stage2.