How Lodash Optimizes Path String Parsing in _.property
Lodash accelerates nested object property access through utilities
like _.property and _.get by eliminating
redundant string-to-path parsing overhead. Instead of naively
decomposing string paths on every invocation, the library employs a
multi-tiered strategy involving direct key detection, precompiled
regular expression tokenization, and an internal capped memoization
cache. This architecture ensures that deep path resolution remains fast
and memory-safe even when evaluating thousands of repetitive
lookups.
The Fast-Path Check with
isKey
Before initiating any parsing logic, Lodash determines whether
parsing is necessary at all. The internal castPath helper
checks if the supplied value is already an array. If it is a string, it
delegates to the isKey utility.
The isKey function checks if the target string can be
treated as a direct property name on the target object. It evaluates
whether the string contains deep path characters—specifically dots
(.), opening brackets ([), or closing brackets
(])—or if the property already exists directly on the
object. If the string contains none of these structural characters,
Lodash skips path parsing entirely and treats the string as a single,
direct property lookup.
Tokenization via Precompiled Regular Expressions
When a string contains deep path notation, Lodash passes it to
stringToPath. Parsing structured accessors like
'a.b[0].c' into discrete segments
(['a', 'b', '0', 'c']) is handled via precompiled regular
expressions rather than dynamic string splitting.
Lodash defines specific regex patterns ahead of time, primarily
rePropName:
const rePropName = /[^.[\]]+|\[(?:([^"'][^[]*)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;This regular expression matches:
- Standard property names separated by dots
(
[^.[\]]+). - Numeric or unquoted bracket indices
(
\[([^"'][^[]*)\]). - Single- or double-quoted bracket keys, properly handling escaped
characters (
\[(["'])...\]).
Lodash executes this pattern using
String.prototype.replace to iterate through matches,
stripping away leading dots and unescaping quoted keys before pushing
each token into a clean segment array.
Capped Memoization Cache
Because tokenizing strings with regular expressions is
computationally expensive, Lodash wraps stringToPath with
an internal memoization wrapper called memoizeCapped.
Under this mechanism:
- The first time a path string (e.g.,
'user.profile.name') is encountered, the regex parser runs and the resulting array of property keys is stored in an internal cache. - Subsequent calls passing identical path strings retrieve the pre-computed array in \(O(1)\) time, completely bypassing regex execution.
- To prevent unbounded memory growth in long-running Node.js processes
or single-page applications, the cache is restricted by
MAX_MEMOIZE_SIZE(set to 500 entries). When the cache exceeds this limit, it is cleared, preventing memory leaks while retaining high hit rates for common application paths.
Final Execution via Segment Iteration
Once castPath returns the array of path segments—either
from the memoized cache or newly generated—the
basePropertyDeep helper takes over. It iterates through the
array using a simple while loop, sequentially traversing
each nested level of the target object:
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;
}By isolating the complex string parsing phase into a memoized,
regex-driven step, Lodash ensures that the repeated execution of
_.property performs nearly as fast as native, static
property traversals.