String.prototype.matchAll()
Метод matchAll()
(шукати всі збіги) значень String
повертає ітератор з усіма результатами зіставлення свого рядка з регулярним виразом, в тому числі групи захоплення.
Спробуйте його в дії
Синтаксис
matchAll(regexp)
Параметри
regexp
Об'єкт регулярного виразу, або ж будь-який об'єкт, що має метод
Symbol.matchAll
.Якщо
regexp
не є об'єктомRegExp
і не має методуSymbol.matchAll
, то він неявно перетворюється наRegExp
за допомогоюnew RegExp(regexp, 'g')
.Якщо
regexp
є регулярним виразом, то цей регулярний вираз повинен мати позначку глобальності (g
), а інакше – викидаєтьсяTypeError
.
Повернене значення
Ітерований об'єкт-ітератор (непридатний до повторного перебирання) зі збігами, або порожній ітератор, якщо жодного збігу не знайдено. Кожне значення, видане таким ітератором, є масивом з такою ж структурою, як повернене значення методу RegExp.prototype.exec()
.
Винятки
TypeError
Викидається, коли
regexp
є регулярним виразом, але не має позначки глобальності (g
) (тобто його властивістьflags
не містить"g"
).
Опис
Реалізація String.prototype.matchAll
робить небагато, крім виклику метода Symbol.matchAll
свого аргументу з вихідним рядком як першим параметром (коли не рахувати додаткової валідації вихідних даних щодо того, що регулярний вираз є глобальним). Фактична реалізація надходить із RegExp.prototype[Symbol.matchAll]
.
Приклади
Методи Regexp.prototype.exec() і matchAll()
Без matchAll()
отримувати всі збіги можна за допомогою викликів regexp.exec()
(і регулярних виразів з позначкою g
) у циклі:
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
let match;
while ((match = regexp.exec(str)) !== null) {
console.log(
`Знайдено слово ${match[0]}, початок=${match.index}, закінчення=${regexp.lastIndex}.`,
);
}
// Знайдено слово football, початок=6, закінчення=14.
// Знайдено слово foosball, початок=16, закінчення=24.
За наявності методу matchAll
є можливість уникати циклу while
і використання методу exec
із g
. Це можливо завдяки тому, що повертається ітератор, який можна використовувати зі зручнішими конструкціями – for...of
, розгортанням масиву і Array.from()
:
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
const matches = str.matchAll(regexp);
for (const match of matches) {
console.log(
`Знайдено слово ${match[0]}, початок=${match.index}, закінчення=${
match.index + match[0].length
}.`,
);
}
// Знайдено слово football, початок=6, закінчення=14.
// Знайдено слово foosball, початок=16, закінчення=24.
// ітератор зі збігами вичерпується після перебирання у for...of
// Новий виклик matchAll створить новий ітератор
Array.from(str.matchAll(regexp), (m) => m[0]);
// [ "football", "foosball" ]
Якщо прапорець g
опущено, метод matchAll
викине виняток.
const regexp = /[a-c]/;
const str = "abc";
str.matchAll(regexp);
// TypeError
Метод matchAll
для своїх потреб створює клон глобального об'єкта RegExp
. Тому, на відміну від використання методу regexp.exec()
, властивість lastIndex
об'єкта RegExp
не змінюється під час сканування рядка.
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" ]
Проте це означає, що на відміну від використання regexp.exec()
у циклі, не можна змінювати lastIndex
для перемотування регулярного виразу вперед або назад.
Кращий доступ до груп захоплення (ніж у String.prototype.match())
Іншою привабливою причиною використати matchAll
є покращений доступ до груп захоплення.
Під час застосування match()
з прапорцем глобального пошуку g
групи захоплення ігноруються:
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";
str.match(regexp); // ['test1', 'test2']
За допомогою matchAll
можна легко отримати доступ до груп:
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]
Застосування matchAll() вкупі з об'єктом, що не є RegExp, але має реалізацію [Symbol.matchAll]()
Якщо об'єкт має метод Symbol.matchAll
, то він може використовуватися як власний шукач збігів. Повернене значення Symbol.matchAll
стає поверненим значенням matchAll()
.
const str = "Гм, це цікаво.";
str.matchAll({
[Symbol.matchAll](str) {
return [["Так, це цікаво."]];
},
}); // returns [["Yes, it's interesting."]]
Специфікації
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
matchAll
|
Chrome Full support 73 | Edge Full support 79 | Firefox Full support 67 | Internet Explorer No support Ні | Opera Full support 60 | Safari Full support 13 | WebView Android Full support 73 | Chrome Android Full support 73 | Firefox for Android Full support 67 | Opera Android Full support 52 | Safari on iOS Full support 13 | Samsung Internet Full support 11.0 | Deno Full support 1.0 | Node.js Full support 12.0.0 |
Дивіться також
- Поліфіл методу
String.prototype.matchAll
доступний уcore-js
String.prototype.match()
- Посібник Регулярні вирази
- Посібник Групи та зворотні посилання
RegExp
RegExp.prototype.exec()
RegExp.prototype.test()
RegExp.prototype[Symbol.matchAll]()