Yesterday I shared with you a utility function to recurrently loop an object in JS, one of the features it has, is that you can get an array with a path to the nested object that is currently being looped. However, when working with nested objects, you may want to retrieve or verify data from a specific path at any given moment, that's what today's utility functions do.
-
getDataFromObj(obj, path)
: retrieve data from a given path in an object -
isValidObjPath(obj, path)
: verify if a given path exists in an object
getDataFromObj(obj, path)
Feel free to copy and paste this code
/**
* Retrieves data from an object on a given path
* @param {Object} obj the object to get the data from
* @param {string[]} path an array of strings containing the keys of the object to look at
* @returns {*} the retrieved data or a Reference Error if not found
*/
function getDataFromObj(obj, path){
// Validate arguments
if(getType(obj) != "object"){
throw TypeError("The `obj` argument is not an object");
}
if(getType(path) != "array"){
throw TypeError("The `path` argument is not an array");
}
// Get the data or a ReferenceError if not found
const data = (()=>{
let currentData = obj;
for(let i = 0; i < path.length; i +=1 ){
if(Object.keys(currentData).includes(path[i])){
currentData = currentData[path[i]];
continue;
} else{
currentData = ReferenceError("The object path is not defined");
break;
}
}
return currentData;
})();
return data;
}
/**
* A method to detect data types more accurately
* Credits: Chris Ferdinandi, https://gomakethings.com/
* @param {*} data the data to be verified
* @returns {String} the data type
*/
function getType(data){
return Object.prototype.toString.call(data).toLowerCase().slice(8, -1)
}
/**
* License: MIT, https://opensource.org/license/mit
* Copyright (c) 2024 Rodrigo Isaias Calix
*/
Usage:
You must pass 2 arguments:
obj
: The object from where you want to retrieve the data
path
: An array indicating the sequence to follow
If the path exists it will return the value (even if the value is undefined
), if the path doesn't exist it will return a ReferenceError
object, it doesn't throw an error, just returns the error object.
const products = {
computers: {
laptop: 20,
desktop: 15,
mini: 8
},
cameras: 20,
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
other: undefined
}
}
}
// This would log 25
console.log(getDataFromObj(products, ["externalDevices", "keyboard", "bluetooth"]))
// this would return a ReferenceError object (not a throw, just the error object)
console.log(getDataFromObj(products, ["externalDevices", "mouse"]))
// this would return `undefined`
console.log(getDataFromObj(products, ["externalDevices", "keyboard", "other"]))
isValidObjPath(obj, path)
The utility code:
/**
* verify if an object has an specific path
* @param {Object} obj the object to be verified
* @param {string[]} path an array of strings containing the keys of the object to look at
* @returns {Boolean} `true` if found, otherwise `false`
*/
function isValidObjPath(obj, path){
// Validate arguments
if(getType(obj) != "object"){
throw TypeError("The `obj` argument is not an object");
}
if(getType(path) != "array"){
throw TypeError("The `path` argument is not an array");
}
// shallow copy of the object to be verified
let currentData = obj;
// Verify the path
for(let i = 0; i < path.length; i +=1 ){
if(Object.keys(currentData).includes(path[i])){
currentData = currentData[path[i]];
continue;
} else{
return false;
}
}
return true;
}
/**
* A method to detect data types more accurately
* Credits: Chris Ferdinandi, https://gomakethings.com/
* @param {*} data the data to be verified
* @returns {String} the data type
*/
function getType(data){
return Object.prototype.toString.call(data).toLowerCase().slice(8, -1)
}
/**
* License: MIT, https://opensource.org/license/mit
* Copyright (c) 2024 Rodrigo Isaias Calix
*/
Usage:
You must pass 2 arguments:
obj
: The object that you want to verify if a path exists
path
: An array indicating the sequence to follow
If the path you are searching exists, it will return true
, otherwise it will return false
const products = {
computers: {
laptop: 20,
desktop: 15,
mini: 8
},
cameras: 20,
externalDevices: {
keyboard: {
usb: 45,
bluetooth: 25,
other: undefined
}
}
}
// This would log true
console.log(isValidObjPath(products, ["externalDevices", "keyboard", "bluetooth"]))
// this would log false
console.log(isValidObjPath(products, ["externalDevices", "mouse"]))
// this would log true
console.log(isValidObjPath(products, ["externalDevices", "keyboard", "other"]))
Why an array as the path instead of a string with slashes or dots? (e.g. "computers.laptop")
Because object property names can also be a string with a large range set of characters, which includes dots, so, for example, "computers.laptop": {[...]}
would be a valid object, an array would allow more flexibility and accuracy.
If you found this useful, I'll be sharing more content like this on DEV!
You can also find me on X: https://x.com/schemetastic
And remember to save it for later 🔖
Top comments (0)