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:

  1. Active Traversal: As long as the current object is not null or undefined, the loop reads the next property: object[toKey(path[index++])].
  2. Short-Circuiting: If any intermediate property in the chain is non-existent, null, or undefined, the loop evaluates object != null as false and terminates immediately.
  3. Guard Against TypeErrors: Because the loop breaks prior to reading subsequent keys, the JavaScript engine never attempts to access a property on null or undefined, avoiding native TypeError exceptions.
  4. Final Check: After loop termination, baseGet checks 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 to false, and baseGet explicitly returns undefined.

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.