阿里云主机折上折
  • 微信号
Current Site:Index > String.prototype.matchAll()

String.prototype.matchAll()

Author:Chuan Chen 阅读数:18348人阅读 分类: JavaScript

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:

  1. The iterator is lazily evaluated, making it suitable for streaming
  2. Convert to an array if results need to be reused
  3. 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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.