Lodash valuesIn Execution Path for Prototype Values
This article traces the internal execution path Lodash traverses when
resolving and mapping prototype property values using
_.valuesIn. It details the step-by-step lifecycle from the
public API call through key discovery, prototype-chain enumeration, and
dynamic property access, showing precisely how inherited properties are
gathered and returned.
The Entry Point:
valuesIn
When _.valuesIn(object) is called, Lodash begins by
validating the target argument. If the target is null or
undefined, the method immediately returns an empty array.
If the target is a valid object or primitive wrapper,
valuesIn delegates to two internal routines:
baseValues and keysIn:
function valuesIn(object) {
return object == null ? [] : baseValues(object, keysIn(object));
}The execution path splits into two distinct phases: discovering all
enumerable property identifiers (both own and inherited) via
keysIn, and dynamically projecting those identifiers to
their respective values via baseValues.
Enumeration Path:
keysIn and baseKeysIn
To access inherited prototype properties, Lodash must inspect the
prototype chain. The keysIn utility invokes
baseKeysIn(object), which implements the traversal
logic:
- Object Type Validation: Lodash verifies that the
argument is an object using
isObject(object). Primitives are converted to objects usingObject(object)to permit safe prototype inspection. - Prototype Edge Case Check: Lodash determines
whether the input itself is a prototype object via
isPrototype(object). If it is, the runtime skips standard constructor keys to prevent accidental pollution or circular references. - Dynamic Chain Traversal:
baseKeysInexecutes a JavaScriptfor...instatement:for (const key in object) { result.push(key); }
Because the ECMAScript specification dictates that
for...in walks the target's entire
[[Prototype]] chain, this loop dynamically captures all
enumerable keys residing on upstream prototypes up to, but not
including, Object.prototype.
Dynamic Mapping:
baseValues
Once baseKeysIn returns the accumulated array of own and
prototype keys, execution transfers to baseValues:
function baseValues(object, props) {
return arrayMap(props, (key) => object[key]);
}Inside baseValues, Lodash passes the discovered keys to
arrayMap. For every key in the props array,
dynamic property access (object[key]) is triggered.
When JavaScript evaluates object[key], the engine first
looks for an own property on object. If the property does
not exist directly on the instance, the V8/JavaScript engine walks the
internal [[Prototype]] link dynamically until it resolves
the value on the ancestor prototype where it was defined.
Isolating Strictly Prototype Values
Because _.valuesIn aggregates both own properties and
prototype properties into a single output, strictly prototype values are
those associated with keys where
Object.prototype.hasOwnProperty.call(object, key) evaluates
to false.
In Lodash's full execution path:
keysIndynamically harvests own and prototype keys viabaseKeysInusingfor...in.- Inherited keys resolve strictly up the prototype chain.
baseValuesiterates the combined keys, querying the instance.- The JavaScript runtime’s internal
[[Get]]operation executes for each key, dynamically retrieving the corresponding value from the prototype.