How Lodash _.pick Handles Object Memory Allocation

When invoking _.pick in the Lodash JavaScript library, the engine creates a brand-new object on the heap while copying selected property descriptors and references from the source object. This article examines the internal structural memory mapping generated during this process, focusing on heap allocation, V8 Hidden Classes (Shapes), reference graph mutations, and memory retention dynamics.

Fresh Heap Allocation and Root Identification

Calling _.pick(source, [paths]) instructs Lodash to evaluate the specified paths and construct a completely new container object. Under the hood—typically routing through internal utilities like basePick or basePickBy—the method allocates an empty plain object ({}) in the JavaScript runtime’s nursery space (young generation heap).

This newly generated object receives:

Hidden Classes and Transition Trees

In engines like V8, objects rely on Hidden Classes (also known as "Shapes" or "Maps") to optimize property access via Inline Caches (ICs).

  1. Initial Shape: The fresh target object begins with the root empty object shape (Map0).
  2. Dynamic Transitions: As _.pick iterates over the allowed properties and writes them onto the new object, the engine moves along a transition tree:
    • Adding Property A transitions the object from Map0 to Map1.
    • Adding Property B transitions it from Map1 to Map2.
  3. Shape Divergence: Because _.pick dynamically assigns properties at runtime based on the array order of the keys provided, the resulting object may not share the same Hidden Class as an object instantiated with an object literal containing the same keys in a different order. If a large number of dynamic keys are picked inconsistently across invocations, V8 may bypass the transition tree entirely and downgrade the object to "dictionary mode" (slow mode), storing properties in a hash table rather than fixed offset slots.

Pointer Mapping: Shallow Copy Architecture

The structural memory mapping created by _.pick is strictly shallow. It isolates the top-level container while preserving internal reference links:

Source Object [Address: 0x001]
 ├── primitive: 42 (Value copy)
 └── nestedRef: ──┐
                  │
Picked Object [Address: 0x002]
 └── nestedRef: ──┴──> [Heap Allocation: 0x0A9] (Shared Reference)

As a result, a split reference topology is formed. Mutating a nested reference via the picked object directly mutates the source object's underlying structural data, as both pointers resolve to the exact same offset in memory.

Property Storage: In-Object vs. Backing Store

When _.pick assigns the target properties, V8 determines where these values physically live relative to the object header:

Garbage Collection and Retainment Implications

The structural memory mapping produced by _.pick directly impacts Garbage Collection (GC) reachability graphs.

Because references to nested objects are retained within the newly allocated root, selecting a single deeply nested object or property via _.pick keeps that entire referenced sub-tree reachable from the root. If the source object is subsequently set to null to free memory, any sub-objects referenced by the picked object cannot be swept by the Mark-and-Sweep garbage collector, preserving their residency in the heap.