String matchAll vs Lodash for Regex Matching
The introduction of String.prototype.matchAll in
ECMAScript 2020 provides a native, streamlined way to capture multiple
regular expression matches alongside their capturing groups.
Historically, JavaScript lacked an intuitive built-in approach for this
task, leading developers to rely on utility libraries like Lodash or
verbose RegExp.prototype.exec loops to parse complex string
patterns. By delivering an iterable containing complete match arrays,
matchAll makes external regex utility patterns and Lodash
workarounds obsolete for string extraction.
The Limitation of Traditional Native Methods
Prior to matchAll, developers primarily relied on two
native options: String.prototype.match and
RegExp.prototype.exec.
When used with the global flag (/g),
String.prototype.match returns all matching substrings but
discards capturing groups, match indices, and named capture groups. To
preserve capturing groups, developers were forced to use
RegExp.prototype.exec inside a mutable while
loop, manually tracking the state of the regular expression:
const regex = /t(e)(st(\d?))/g;
const text = 'test1test2';
let match;
while ((match = regex.exec(text)) !== null) {
console.log(match);
}This approach is prone to errors, such as infinite loops if the regex lacks the global flag or if state management fails.
How Lodash Filled the Gap
Because native regex extraction was cumbersome, developers regularly
turned to Lodash to handle repetitive string processing and token
extraction. Functions like _.words provided simpler
string-splitting mechanisms, while custom Lodash pipelines were
frequently used to wrap and map over RegExp.exec
iterations. Developers used functional utilities to iterate cleanly over
strings, transform capture groups, and avoid maintaining stateful
while loops directly in application code.
While Lodash does not feature an exact _.matchAll
function, developers heavily depended on its collection and string
processing methods to compensate for JavaScript's native shortcomings
regarding iterative regex parsing.
How
String.prototype.matchAll Replaces Utility Helpers
String.prototype.matchAll completely solves the
limitations of match and the verbosity of
exec. Calling matchAll returns an iterator of
match objects, each containing the full match, all capture groups, the
index where the match was found, the original input string, and any
named groups defined in the pattern.
Because the returned value is an iterable, it integrates naturally
with modern JavaScript features like for...of loops, array
destructuring, and Array.from:
const regex = /t(e)(st(\d?))/g;
const text = 'test1test2';
// Clean array of matches with all groups preserved
const matches = [...text.matchAll(regex)];
matches.forEach(match => {
console.log(match[0]); // full match
console.log(match[1]); // first capture group
console.log(match.index); // start index
});Unlike RegExp.prototype.exec, matchAll
handles regex state internally without mutating the original
lastIndex on the regular expression, ensuring safer, pure
functional operations.
Eliminating the Need for External Helpers
With String.prototype.matchAll, the need to rely on
external library routines or verbose loops to extract structured token
data disappears. Developers gain the following advantages without
importing utility libraries:
- Group Retention: Capture groups and named capture groups are preserved across all global matches.
- Immutability: Internal regex tracking prevents side
effects without manual resets of
regex.lastIndex. - Idiomatic Processing: Native iterables allow
immediate transformation via standard array methods like
.map(),.filter(), and.reduce(). - Reduced Bundle Size: Removing third-party string and regex iteration wrappers reduces application dependencies and overall bundle overhead.