Why Use Lodash _.hasIn for Prototype Chain Checks
In modern JavaScript development, verifying whether an object
contains a specific property is a routine task, but standard methods
often fail when properties reside on the object's prototype rather than
the instance itself. The Lodash library provides two distinct functions
for property detection: _.has, which only checks an
object's direct (own) properties, and _.hasIn, which
traverses the entire prototype chain. Developers use
_.hasIn primarily to verify the existence of inherited
methods, class behaviors, and properties in deeply nested structures
without triggering runtime errors or writing verbose fallback
checks.
The Core Difference:
_.has vs. _.hasIn
To understand why _.hasIn is necessary, you must
distinguish between "own" properties and inherited properties.
_.has(object, path): Behaves likeObject.prototype.hasOwnProperty(). It checks only the direct properties assigned specifically to that target object._.hasIn(object, path): Behaves like JavaScript's nativeinoperator. It checks the target object, and if the property is not found, it continues up the prototype chain until it either finds the property or reaches the end of the chain (null).
const parent = { inheritedProp: 'I am inherited' };
const child = Object.create(parent);
child.ownProp = 'I am direct';
_.has(child, 'inheritedProp'); // false
_.hasIn(child, 'inheritedProp'); // trueKey Reasons to Use
_.hasIn
1. Handling ES6 Classes and Inheritance
When using ES6 classes, methods defined in a class definition are
placed on the class's prototype, not directly on the instantiated
instance. If a utility function needs to check whether an instance
implements a specific method, _.has will return
false. Using _.hasIn correctly detects class
methods:
class Vehicle {
startEngine() {
return true;
}
}
const car = new Vehicle();
_.has(car, 'startEngine'); // false (method is on Vehicle.prototype)
_.hasIn(car, 'startEngine'); // true2. Working with Native and Third-Party Objects
Many environments, including browser DOM nodes, Node.js streams, and
third-party SDKs, rely heavily on prototype inheritance to share
functionality across objects. For example, standard methods like
toString or DOM APIs exist on prototype chains. When
validating external input or wrappers, _.hasIn ensures you
do not produce false negatives on inherited APIs.
3. Safe Nested Path Navigation
Native property checks using the in operator can fail if
an intermediate key is null or undefined,
throwing a TypeError. _.hasIn accepts path
arrays or dot-notation strings (e.g.,
'config.settings.timeout') and traverses each level safely.
If any intermediate parent in the path is missing, _.hasIn
cleanly returns false instead of crashing the
application.
4. Avoiding Prototype Pollution Edge Cases
Directly invoking object.hasOwnProperty(key) can lead to
errors if an object is created with Object.create(null)
(which lacks Object.prototype), or if the
hasOwnProperty property has been overwritten.
_.hasIn avoids these pitfalls by wrapping the verification
safely inside Lodash’s internal mechanics.
Summary
Developers choose _.hasIn whenever an object's complete
interface—both its own properties and everything inherited through the
prototype chain—must be evaluated. It provides a defensive, safe, and
clean alternative to combining the native in operator with
manual null checks across nested data structures.