JavaScript objects are often nested in other objects.
Also, they’re dynamic.
Therefore, we may have to check if a nested property exists in an object.
In this article, we’ll look at how to check if a nested property exists in an object.
Write Our Own Function
We can write our own JavaScript function to check if a deeply nested property exists in an object.
For instance, we can write:
const checkNested = (obj, ...props) => {
for (const prop of props) {
if (!obj || !Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
obj = obj[prop];
}
return true;
}
const obj = {
level1: {
level2: {
level3: 'level3'
}
}
};
console.log(checkNested(obj, 'level1', 'level2', 'level3'));
console.log(checkNested(obj, 'level1', 'level2', 'bar'));
We create the checkNested
function with the obj
parameter and the props
rest parameters.
obj
is the object we’re checking.
props
has an array of properties that forms the path to the nested property we’re looking for.
In the function, we loop through the props
array to traverse obj
to find the nested property.
To do that, we check if obj
is falsy or if hasOwnProperty
returns false
.
If either of them are true
, then we know the property doesn’t exist.
So we return false
.
We call hasOwnProperty
with Object.prototype.hasOwnProperty.call
instead of obj.hasOwnProperty
since obj.hasOwnProperty
can be overridden.
call
takes the this
value for hasOwnProperty
.
prop
is the property name string value.
If we get past the if
block, then we assign obj
to obj[prop]
to look one level deeper.
We can do that since the property is an object.
If the whole loop is iterated through successfully, then we return true
since the path leads to the property we’re looking for.
We test this function with the obj
object, and we can see the first console returns true
.
And the 2nd one returns false
as expected.
Recursively Check for a Given Property
We can also do the check with a recursive function.
For instance, we can write:
const checkNested = (obj, prop, ...restProps) => {
if (obj === undefined) {
return false;
}
if (
restProps.length === 0 &&
Object.prototype.hasOwnProperty.call(obj, prop)
) {
return true;
}
return checkNested(obj[prop], ...restProps);
};
const obj = {
level1: {
level2: {
level3: "level3"
}
}
};
console.log(checkNested(obj, "level1", "level2", "level3"));
console.log(checkNested(obj, "level1", "level2", "foo"));
This checkNested
function is similar to the one we have before.
The difference is that we get the first property from the path we’re looking for.
And the rest stays in the array.
We check if restProp.length
is 0 and if obj
has the prop
property.
If they’re both true
, then we return true
since we traversed the whole path and we found the property.
If they’re anything left in restProps
, then we call checkNested
to drill down one level lower.
And we should get the same result as before.
Optional Chaining Operator
Another way to check if a nested property path exists is to use tyhe optional chaining operator, which is added with ?.
.
This operator is new to ES2020.
For instance, we can write:
const obj = {
level1: {
level2: {
level3: "level3"
}
}
};
const value1 = obj?.level1?.level2?.level3;
const value2 = obj?.level1?.level2?.foo;
console.log(value1);
console.log(value2);
We should see that value1
is 'level3'
and value2
is undefined
since the operator returns the property value if the property exists and undefined
otherwise.
This lets us reduce the amount of work needed to traverse deeply nested properties safely.
Conclusion
We can test for the existence of a deeply nested JavaScript object property with our own code or the optional chaining operator.