Lodash findLastKey Iteration Order Explained

The _.findLastKey method in Lodash iterates over an object's own enumerable properties in reverse to locate the last key satisfying a given predicate. This article examines the exact execution priority that governs the traversal sequence of keys during this operation, explaining how Lodash generates its property list, how the ECMAScript property traversal specification applies, and the resulting reverse evaluation order.

How Lodash Retrieves Keys

To iterate backward, Lodash first extracts the target object’s own enumerable property names using its internal keys implementation (equivalent to Object.keys()). The iteration is handled by internal utilities such as baseForOwnRight, which loops backward through the gathered keys array from length - 1 down to 0.

Because the loop iterates from the end of the array to the beginning, the iteration sequence is the strict reverse of the ECMAScript [[OwnPropertyKeys]] specification order.

The ECMAScript Key Ordering Rules

Under the ECMAScript standard, property keys on ordinary objects are ordered according to the following deterministic rules:

  1. Integer Indexes: Keys that qualify as non-negative integer strings (e.g., "0", "1", "42") are placed first, sorted in ascending numerical order.
  2. String Keys: All other string keys are ordered based on chronological insertion order.
  3. Symbols: Symbol keys are ordered by insertion order (though standard _.findLastKey operates only on string-keyed properties and ignores Symbols).

The Reverse Execution Priority in _.findLastKey

Because _.findLastKey evaluates the properties in the inverse order of this standardized list, the execution priority during iteration is:

  1. String Keys (Reverse Insertion Order): Non-integer string keys are tested first, beginning with the most recently added string property and proceeding backward to the earliest added string property.
  2. Integer Keys (Descending Numerical Order): Once all non-integer string properties have been evaluated, any integer index keys are evaluated next, beginning with the highest numeric index down to the lowest (e.g., "10", then "2", then "0").

Example

Consider the following object:

const obj = {
  a: 1,
  10: 2,
  b: 3,
  2: 4,
  c: 5
};
  1. Standard Object.keys Order: ["2", "10", "a", "b", "c"]
  2. _.findLastKey Iteration Order:
    • "c" (last inserted string key)
    • "b"
    • "a" (first inserted string key)
    • "10" (highest integer index)
    • "2" (lowest integer index)

The predicate function passed to _.findLastKey will execute on each property in this exact sequence until it returns a truthy value or exhausts all own enumerable keys.