How Lodash toPath Parses String Accessors
Lodash's _.toPath utility converts deep object property
paths from strings into sequential arrays of property keys and indices.
This article explains the internal mechanics of _.toPath,
detailing how the library normalizes edge-case inputs, leverages
memoization for performance, and executes a dedicated regular expression
engine to cleanly extract dot-separated, bracket-indexed, and quoted
object accessors into distinct array segments.
Input Normalization and Edge Cases
Before running any parsing logic, _.toPath checks the
data type of the input:
- Arrays: If the input is already an array, Lodash maps over its elements to ensure symbols and keys are preserved, returning a new array without running string extraction.
- Symbols: JavaScript
Symbolprimitives are wrapped directly in a single-element array ([value]). - Nullish Values: Passing
nullorundefinedreturns an empty array ([]). - Primitives: Numbers and other primitives are converted to their string representations before further processing.
Performance Optimization with Memoization
String manipulation and regex evaluations are computationally
expensive when performed repeatedly in deeply nested data
transformations. To mitigate this, Lodash routes string parsing through
an internal wrapper called memoizeCapped.
This cache stores the parsed array results for up to 500 unique path
strings. If the cache reaches this threshold, it clears completely to
prevent memory leaks in long-running Node.js processes or single-page
applications. If an incoming path string exists in the cache,
_.toPath immediately returns the cached array.
The Parsing Regular Expression
When a path string misses the cache, Lodash invokes an internal
helper named stringToPath. This function relies on a
comprehensive regular expression (rePropName) designed to
capture three distinct accessor styles:
- Standard Identifiers: Matches standard alphanumeric
property keys separated by dots (e.g.,
foo.bar). - Unquoted Bracketed Notation: Matches numeric
indices or property names inside square brackets without quotes (e.g.,
[0]or[value]). - Quoted Bracketed Notation: Matches single- or
double-quoted strings within brackets, allowing properties that contain
spaces, special characters, or literal dots (e.g.,
['foo.bar']or["key with spaces"]).
In Lodash's source code, the pattern is structured roughly as:
const rePropName = /[^.[\]]+|\[(?:([^"'][^[]*)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;Segment Extraction and Sanitization
The stringToPath function initializes an empty array and
uses String.prototype.replace alongside
rePropName as an iterator to capture matches
sequentially:
- Dot Removal: Standard dot accessors are captured directly as their bare string names.
- Bracket Stripping: When an accessor is enclosed in
brackets, the outer brackets are removed. If the segment is an index
(such as
[0]), the number is captured as a string ("0"). - Quote and Escape Handling: If an accessor contains
quotes (such as
["a.b"]), the regular expression strips the surrounding quotation marks. Any escaped characters inside the quoted string (such as\\"or\\.) have their escaping backslashes resolved.
Each processed match is pushed to the result array. For example, the input path string:
"user.posts[0]['meta.data'].id"is evaluated step-by-step into:
["user", "posts", "0", "meta.data", "id"]Once the regex finishes traversing the string, the resulting array of
property strings is cached and returned, enabling other Lodash utilities
like _.get, _.set, and _.has to
traverse nested objects reliably.