String.prototype.matchAll()

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

Phương thức matchAll() của các giá trị String trả về một iterator của tất cả các kết quả khớp của string này với một biểu thức chính quy, bao gồm cả các nhóm bắt.

Try it

const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";

const array = [...str.matchAll(regexp)];

console.log(array[0]);
// Expected output: Array ["test1", "e", "st1", "1"]

console.log(array[1]);
// Expected output: Array ["test2", "e", "st2", "2"]

Cú pháp

js
matchAll(regexp)

Tham số

regexp

Một đối tượng biểu thức chính quy, hoặc bất kỳ đối tượng nào có phương thức Symbol.matchAll.

Nếu regexp không phải là đối tượng RegExp và không có phương thức Symbol.matchAll, nó được ngầm định chuyển đổi thành RegExp bằng cách sử dụng new RegExp(regexp, 'g').

Nếu regexp là regex, thì nó phải có cờ global (g) được đặt, hoặc một TypeError sẽ bị ném.

Giá trị trả về

Một đối tượng iterator có thể lặp (không thể khởi động lại) của các kết quả khớp hoặc một iterator rỗng nếu không tìm thấy kết quả khớp. Mỗi giá trị được tạo ra bởi iterator là một mảng có hình dạng tương tự như giá trị trả về của RegExp.prototype.exec().

Ngoại lệ

TypeError

Ném ra nếu regexp là regex không có cờ global (g) được đặt (thuộc tính flags của nó không chứa "g").

Mô tả

Việc triển khai String.prototype.matchAll không làm nhiều thứ khác ngoài việc gọi phương thức Symbol.matchAll của đối số với string là tham số đầu tiên (ngoài việc kiểm tra thêm đầu vào rằng regex là global). Việc triển khai thực tế đến từ RegExp.prototype[Symbol.matchAll]().

Ví dụ

Regexp.prototype.exec() và matchAll()

Không có matchAll(), có thể sử dụng các lời gọi đến regexp.exec() (và regex với cờ g) trong một vòng lặp để lấy tất cả các kết quả khớp:

js
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
let match;

while ((match = regexp.exec(str)) !== null) {
  console.log(
    `Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`,
  );
}
// Found football start=6 end=14.
// Found foosball start=16 end=24.

Với matchAll() có sẵn, bạn có thể tránh vòng lặp whileexec với g. Thay vào đó, bạn nhận được một iterator để sử dụng với các cấu trúc tiện lợi hơn như for...of, trải rộng mảng, hoặc Array.from():

js
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
const matches = str.matchAll(regexp);

for (const match of matches) {
  console.log(
    `Found ${match[0]} start=${match.index} end=${
      match.index + match[0].length
    }.`,
  );
}
// Found football start=6 end=14.
// Found foosball start=16 end=24.

// matches iterator is exhausted after the for...of iteration
// Call matchAll again to create a new iterator
Array.from(str.matchAll(regexp), (m) => m[0]);
// [ "football", "foosball" ]

matchAll sẽ ném ngoại lệ nếu thiếu cờ g.

js
const regexp = /[a-c]/;
const str = "abc";
str.matchAll(regexp);
// TypeError

matchAll nội bộ tạo một bản sao của regexp — vì vậy, không giống như regexp.exec(), lastIndex không thay đổi khi string được quét.

js
const regexp = /[a-c]/g;
regexp.lastIndex = 1;
const str = "abc";
Array.from(str.matchAll(regexp), (m) => `${regexp.lastIndex} ${m[0]}`);
// [ "1 b", "1 c" ]

Tuy nhiên, điều này có nghĩa là không giống như sử dụng regexp.exec() trong một vòng lặp, bạn không thể thay đổi lastIndex để làm regex tiến hay lùi.

Truy cập tốt hơn vào các nhóm bắt (hơn String.prototype.match())

Một lý do thuyết phục khác cho matchAll là khả năng truy cập được cải thiện vào các nhóm bắt.

Các nhóm bắt bị bỏ qua khi sử dụng match() với cờ global g:

js
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";

str.match(regexp); // ['test1', 'test2']

Sử dụng matchAll, bạn có thể truy cập các nhóm bắt một cách dễ dàng:

js
const array = [...str.matchAll(regexp)];

array[0];
// ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4]
array[1];
// ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4]

Sử dụng matchAll() với đối tượng không phải RegExp triển khai [Symbol.matchAll]()

Nếu một đối tượng có phương thức Symbol.matchAll, nó có thể được sử dụng như một matcher tùy chỉnh. Giá trị trả về của Symbol.matchAll trở thành giá trị trả về của matchAll().

js
const str = "Hmm, this is interesting.";

str.matchAll({
  [Symbol.matchAll](str) {
    return [["Yes, it's interesting."]];
  },
}); // returns [["Yes, it's interesting."]]

Đặc tả

Specification
ECMAScript® 2027 Language Specification
# sec-string.prototype.matchall

Tương thích trình duyệt

Xem thêm