How Lodash _.forIn Iterates Inherited Properties

Lodash's _.forIn method traverses an object's enumerable properties, encompassing both direct ("own") properties and those inherited through its prototype chain. By wrapping native JavaScript iteration behaviors and coupling them with customizable iteratee execution, _.forIn provides a reliable, cross-environment way to process inherited states. This article explains the underlying mechanism of _.forIn, examines how it differs from methods like _.forOwn, and illustrates its mechanics with practical examples.

The Core Mechanism Behind _.forIn

At its core, _.forIn relies on the native JavaScript for...in statement, which is inherently designed to traverse both own and inherited enumerable properties across an object's prototype chain.

Internally, Lodash builds _.forIn using higher-order factory functions, primarily createBaseFor() and baseFor(). Unlike standard array or object traversal functions in Lodash that extract keys into an array using Object.keys() (which only retrieves an object’s own enumerable properties), _.forIn avoids eager key extraction. Instead, it delegates the traversal directly to an iteration loop that allows JavaScript's prototype lookup resolution to evaluate every enumerable property in the chain.

The basic internal flow operates as follows:

  1. Object Validation: Lodash casts or normalizes the target input to ensure it can be treated as an object.
  2. Loop Execution: A specialized loop walks over the object using native prototype-traversing iteration logic.
  3. Iteratee Invocation: For each property, the callback iteratee is invoked with three arguments: (value, key, object).
  4. Early Exit Support: If the iteratee explicitly returns false, _.forIn halts iteration immediately, offering an optimization not natively available in standard for...in statements without explicit break handling.

_.forIn vs. _.forOwn

The primary distinction between _.forIn and _.forOwn is the filtering of inherited properties:

Practical Code Example

Consider an example using object inheritance through Object.create():

const _ = require('lodash');

// Define a prototype object
const vehicle = {
  hasWheels: true,
  drive() {
    return 'Moving';
  }
};

// Create a new object inheriting from vehicle
const car = Object.create(vehicle);
car.make = 'Toyota';
car.model = 'Corolla';

// Using _.forIn to iterate
_.forIn(car, (value, key) => {
  console.log(`${key}: ${value}`);
});

Output:

make: Toyota
model: Corolla
hasWheels: true
drive: [Function: drive]

In this example, make and model are own properties of car. hasWheels and drive are inherited from vehicle. Because _.forIn does not enforce property ownership, all four keys are visited.

Iteration Rules and Caveats

When utilizing _.forIn, several behaviors of JavaScript prototype iteration apply: