How Lodash _.at Handles Unreachable Paths
The Lodash method _.at extracts values from an object
corresponding to specified paths and returns them as a new array. This
article examines the internal architecture of _.at,
focusing on how it normalizes property paths, navigates nested
structures using safe internal getters, and systematically produces an
array containing undefined elements when encountering
unreachable deep paths without throwing runtime errors.
Path Collection and
Mapping via baseAt
At its entry point, _.at accepts an object and one or
more paths (supplied either as individual arguments or as a flattened
array). The method delegates the core extraction logic to an internal
function named baseAt.
The baseAt function determines the length of the
resulting array based directly on the number of paths requested. It
iterates sequentially over each path argument, ensuring a strict 1-to-1
positional correspondence between the input paths and the output
elements. For each path in the iteration, baseAt executes a
safe retrieval operation to obtain the value, directly assigning
whatever value is returned—including undefined—to the
current index of the output array.
Path Normalization with
castPath
Before navigating the object, each path must be converted into a
standardized sequence of property keys. Lodash executes
castPath, which checks if the path is already an array of
keys. If the path is a string (such as
'user.profile.address.zip' or 'items[0].id'),
Lodash passes it to stringToPath.
stringToPath utilizes a regular expression to tokenize
the string into individual property names and array indexes, returning
an array of string keys. This internal parser is memoized to avoid
redundant regular expression processing across repeated calls.
Traversal and
Short-Circuiting with baseGet
Once the path is decomposed into a key array, the resolution is
handed off to baseGet, the same internal engine powering
_.get. The baseGet function executes a
standard while loop that advances through the path segments
sequentially:
function baseGet(object, path) {
path = castPath(path, object);
let index = 0;
const length = path.length;
while (object != null && index < length) {
object = object[toKey(path[index++])];
}
return (index && index == length) ? object : undefined;
}The systematic generation of undefined hinges on the
condition object != null:
- Active Traversal: As long as the current
objectis notnullorundefined, the loop reads the next property:object[toKey(path[index++])]. - Short-Circuiting: If any intermediate property in
the chain is non-existent,
null, orundefined, the loop evaluatesobject != nullasfalseand terminates immediately. - Guard Against TypeErrors: Because the loop breaks
prior to reading subsequent keys, the JavaScript engine never attempts
to access a property on
nullorundefined, avoiding nativeTypeErrorexceptions. - Final Check: After loop termination,
baseGetchecks if the traversal reached the end of the path (index == length). If the loop exited prematurely due to an unreachable intermediate segment, the condition evaluates tofalse, andbaseGetexplicitly returnsundefined.
Generating the Output Array
Because baseAt pushes the result of baseGet
for every requested path into the destination array, any broken,
missing, or unreachable chain evaluates cleanly to
undefined.
If three paths are provided and all three point to unreachable nested
properties, baseAt runs three distinct baseGet
operations. Each operation terminates safely at the first missing link
and yields undefined, producing a fully populated array of
[undefined, undefined, undefined] matching the exact length
and order of the requested paths.