Lodash forOwnRight and Dynamic Property Deletion

When using Lodash's _.forOwnRight, deleting an object's properties dynamically during iteration does not alter the predefined iteration queue. Because Lodash captures the object's own enumerable keys upfront, the internal evaluation scope retains the full list of property names, resulting in the iteratee executing for deleted properties with an undefined value.

Key Pre-Collection and Snapshotting

Under the hood, _.forOwnRight delegates iteration to internal methods that extract the object's own enumerable string keys before iteration begins. This key extraction relies on Lodash's keys utility, which generates a static array snapshot equivalent to calling Object.keys(object).

Because this array of property names is constructed prior to the first iteration, the traversal list is fixed in memory. The evaluation scope of the loop maintains an index pointer that starts at keys.length - 1 and decrements toward 0.

The Effect of Dynamic Deletion

When a property is deleted using the delete operator inside the iteratee callback, two scenarios occur depending on the iteration order:

  1. Deleting an Already Processed Property: If the iteratee deletes a property that appeared earlier in the reverse traversal (a property located at a higher index in the internal keys array), the deletion has zero impact on the remaining loop cycles.
  2. Deleting an Upcoming Property: If the iteratee deletes a property scheduled for a future step (a property located at a lower index in the keys array), the key remains in the pre-collected key array.

When the decrementing pointer reaches the deleted key, Lodash still invokes the iteratee function. During the invocation:

Evaluation Scope and Execution Context

The evaluation scope of the running loop is bound to the static keys array and the loop index, not to the live state of the object's property descriptor table. Unlike native for...in loops, which dynamically query the object's prototype chain and property status on each tick and typically skip deleted properties, _.forOwnRight operates strictly over its internal array snapshot.

Consequently, the iteratee must explicitly guard against undefined values or verify property presence using Object.prototype.hasOwnProperty.call(object, key) if properties are pruned dynamically during reverse iteration.