David Páez

Working with deeply nested objects

Published: Sun Feb 11 2024
Topics:


The ability to access a deeply nested property is very useful in JavaScript. For instance, consider the following object:

const obj = {
    id: 1,
    details: {
      info: {
        category: 'A'
      }
    }
  };

You could access the category property by using either the bracket notation or the dot notation:

// Using dot notation
obj.details.info.category // Produces value 'A'

// Using bracket notation
obj['details']['info']['category'] // Produces value 'A'

However, sometimes you don't know the property path structure in advance. In those cases, it is useful to have a helper function (which I have called accessNested) that accepts an arbitrarily long string containing the property path:

// Using helper function
// Produces value 'A'
accessNested(obj, 'details.info.category') 

Here is the implementation of the accessNested function:

// Access and return the value of a nested object property by its path
function accessNested(object, prop_path) {
    let parts = prop_path.split('.');
    
    let value = object;
    for (let i=0; i < parts.length; i++) {
        value = value[parts[i]];
    }

    return value;
}

The cool thing about this is that you can use the accessNested function to filter an array of objects that share a specific property, no matter how deeply nested it may be.

Consider the following array of objects:

const arr = [
  {
    id: 1,
    details: {
      info: {
        category: 'A'
      }
    }
  },
  {
    id: 2,
    details: {
      info: {
        category: 'B'
      }
    }
  },
  {
    id: 3,
    details: {
      info: {
        category: 'A'
      }
    }
  }
];

You can get the set of objects whose property details.info.category is equal to A:

arr.filter(item => accessNested(item, 'details.info.category') == 'A');

You could go even further and create another helper function (let's call it filterByPropertyTest), so that you could do this:

filterByPropertyTest(
	arr, 
	'details.info.category',
	(value) => value === 'A'
)

whose arguments are (in sequential order):

The implementation of filterByPropertyTest would be:

// Filter items from an array of objects by testing the value of a nested property
function filterByPropertyTest(array, prop_path, test_function) {
    return array.filter( item => {
        let value = accessNested(item, prop_path);
        return test_function(value);
    });
}
Go up