How Lodash _.has Bypasses Inherited Object Getters

Lodash’s _.has method allows developers to safely check for the existence of a property on an object without triggering side effects from inherited getters. In JavaScript, checking or accessing properties can inadvertently execute getter functions defined higher up on the prototype chain. Lodash avoids this by restricting its lookup exclusively to the target object's own properties and checking for property existence at the internal descriptor level rather than evaluating property values.

Property Evaluation vs. Property Existence

In standard JavaScript, evaluating a property using standard dot notation or bracket notation (object.property) triggers the internal [[Get]] operation. If that property is configured with an accessor descriptor (a getter), JavaScript immediately executes the corresponding function.

Furthermore, checking existence using the in operator traverses the entire prototype chain. If a getter is defined on a prototype—such as Object.prototype or a custom class prototype—standard access patterns risk either evaluating inherited logic or misidentifying inherited properties as direct properties of the instance.

Reliance on hasOwnProperty

Lodash's _.has functionally bypasses inherited object getters by relying internally on Object.prototype.hasOwnProperty.

Instead of resolving the property value, Lodash uses a guarded reference to hasOwnProperty, typically invoked as:

Object.prototype.hasOwnProperty.call(object, key);

This implementation achieves two distinct safeguards:

  1. Halts Prototype Chain Traversal: hasOwnProperty checks only the object's own internal property table. It never ascends the prototype chain. Any getter residing on an ancestor prototype is ignored entirely, ensuring inherited accessors cannot be triggered or evaluated.
  2. Checks Slot Allocation Without Invoking [[Get]]: hasOwnProperty inspects the object's internal property descriptor records rather than reading the property. Because it only determines whether the property key exists on the instance itself, it checks existence without invoking accessor logic, even if the property itself is an "own" getter.

Distinction Between _.has and _.hasIn

Lodash explicitly separates own-property checks from prototype-aware property checks:

Nested Path Traversal

When resolving nested path strings or arrays (such as 'a.b.c'), _.has resolves intermediate segments down to the parent object before executing the final check. For the intermediate objects, Lodash reads the properties to traverse the path, but the terminal property check is executed via hasOwnProperty. Consequently, inherited getters at the target property level are completely isolated from invocation.