String.prototype.matchAll()
String.prototype.matchAll()
is a string method introduced in ECMAScript 2019 (ES11) that addresses the issue of iterating over capture groups in global regular expression matches. It returns an iterator, enabling more efficient handling of complex matching scenarios.
Basic Usage and Syntax
The matchAll()
method accepts a regular expression as an argument and returns an iterator containing all matching results. Unlike the match()
method, it preserves complete capture group information for each match. The syntax is as follows:
str.matchAll(regexp)
regexp
must be a regular expression object; strings are implicitly converted to regex- Throws a
TypeError
if the regex lacks the/g
flag - The returned iterator is not reusable; you must call the method again after traversal
Differences from match()
The traditional match()
method has limitations in global matching:
const str = 'test1test2';
const regex = /t(e)(st(\d?))/g;
// match() loses capture group information
console.log(str.match(regex)); // ['test1', 'test2']
// matchAll() retains complete information
const matches = str.matchAll(regex);
for (const match of matches) {
console.log(match);
}
/*
[
'test1',
'e',
'st1',
'1',
index: 0,
input: 'test1test2',
groups: undefined
]
[
'test2',
'e',
'st2',
'2',
index: 5,
input: 'test1test2',
groups: undefined
]
*/
Capture Group Handling
matchAll()
is particularly useful for handling capture groups in complex regular expressions:
const html = `
<div class="container">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>
`;
const tagRegex = /<(\w+)([^>]*)>([^<]*)<\/\1>/g;
for (const match of html.matchAll(tagRegex)) {
console.log(`Tag: ${match[1]}, Attributes: ${match[2]}, Content: ${match[3]}`);
}
// Tag: div, Attributes: class="container", Content:
// Tag: p, Attributes: , Content: Paragraph 1
// Tag: p, Attributes: , Content: Paragraph 2
Practical Use Cases
Log Analysis
Extracting key information from multi-line logs:
const logs = `
[ERROR] 2023-01-01: Invalid input
[WARN] 2023-01-02: Deprecated API call
[INFO] 2023-01-03: User logged in
`;
const logRegex = /\[(\w+)\] (\d{4}-\d{2}-\d{2}): (.+)/g;
const logEntries = Array.from(logs.matchAll(logRegex),
match => ({
level: match[1],
date: match[2],
message: match[3]
}));
console.log(logEntries);
/*
[
{ level: 'ERROR', date: '2023-01-01', message: 'Invalid input' },
{ level: 'WARN', date: '2023-01-02', message: 'Deprecated API call' },
{ level: 'INFO', date: '2023-01-03', message: 'User logged in' }
]
*/
CSV Parsing
Simple CSV data processing:
function parseCSV(csv) {
const rowRegex = /("(?:[^"]|"")*"|[^,]+)(?:,|$)/g;
return Array.from(csv.matchAll(rowRegex), match => match[1]);
}
const csvData = 'name,age,city\n"John, Jr.",25,"New ""York"""';
console.log(parseCSV(csvData));
// ['name', 'age', 'city', 'John, Jr.', '25', 'New "York"']
Performance Considerations
While matchAll()
provides richer matching information, be mindful of performance when processing very large strings:
- The iterator is lazily evaluated, making it suitable for streaming
- Convert to an array if results need to be reused
- For simple matching scenarios,
match()
may be more efficient
// Performance comparison
const largeText = 'a'.repeat(1000000) + 'b';
console.time('match');
largeText.match(/a/g);
console.timeEnd('match'); // ~5ms
console.time('matchAll');
Array.from(largeText.matchAll(/a/g));
console.timeEnd('matchAll'); // ~8ms
Integration with Other Methods
Can be easily combined with modern JavaScript features:
// Using destructuring to process matches
const text = 'Key1=Value1; Key2=Value2';
const pairRegex = /(\w+)=(\w+)/g;
for (const [, key, value] of text.matchAll(pairRegex)) {
console.log(`${key}: ${value}`);
}
// Key1: Value1
// Key2: Value2
// Using Array.from's mapping function
const configText = 'theme=dark; fontSize=16; animate=true';
const config = Object.fromEntries(
Array.from(
configText.matchAll(/(\w+)=([^;]+)/g),
match => [match[1], match[2]]
)
);
console.log(config); // { theme: 'dark', fontSize: '16', animate: 'true' }
Browser Compatibility
All modern browsers support matchAll()
, but a polyfill is needed for older environments:
// Simple polyfill implementation
if (!String.prototype.matchAll) {
String.prototype.matchAll = function(regexp) {
if (!regexp.global) {
throw new TypeError('matchAll requires global flag');
}
const matches = [];
let match;
while ((match = regexp.exec(this)) !== null) {
matches.push(match);
}
return matches[Symbol.iterator]();
};
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
下一篇:<button>-可点击按钮