1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
---
title: String.prototype.matchAll()
slug: Web/JavaScript/Reference/Global_Objects/String/matchAll
tags:
- JavaScript
- Method
- Prototype
- Reference
- Regular Expressions
- String
translation_of: Web/JavaScript/Reference/Global_Objects/String/matchAll
---
<div>{{JSRef}}</div>
<p><strong><code>matchAll()</code></strong> 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。</p>
<div>{{EmbedInteractiveExample("pages/js/string-matchall.html")}}</div>
<h2 id="语法">语法</h2>
<pre class="syntaxbox"><var>str</var>.matchAll(<var>regexp</var>)</pre>
<h3 id="参数">参数</h3>
<p>regexp</p>
<p> 正则表达式对象。如果所传参数不是一个正则表达式对象,则会隐式地使用 <code>new RegExp(obj)</code> 将其转换为一个 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/RegExp" title="此页面仍未被本地化, 期待您的翻译!"><code>RegExp</code></a> 。</p>
<p> <code>RegExp</code>必须是设置了全局模式<code>g</code>的形式,否则会抛出异常<code>TypeError</code>。</p>
<h3 id="返回值">返回值</h3>
<p>一个迭代器(不可重用,结果耗尽需要再次调用方法,获取一个新的迭代器)。</p>
<h2 id="例子">例子</h2>
<h3 id="Regexp.exec_和_matchAll">Regexp.exec() 和 matchAll()</h3>
<p>在 <code>matchAll</code> 出现之前,通过在循环中调用 <code>regexp.exec()</code> 来获取所有匹配项信息(regexp 需使用 <code>/g</code> 标志):</p>
<pre class="brush: js">const regexp = 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}.`);
// expected output: "Found football start=6 end=14."
// expected output: "Found foosball start=16 end=24."
}</pre>
<p>如果使用 <code>matchAll</code> ,就可以不必使用 while 循环加 exec 方式(且正则表达式需使用 <code>/g</code> 标志)。使用 <code>matchAll</code> 会得到一个迭代器的返回值,配合 <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></code>, <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">array spread</a>, 或者 {{jsxref("Array.from()")}} 可以更方便实现功能:</p>
<pre class="brush: js">const regexp = 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}.`);
}
// expected output: "Found football start=6 end=14."
// expected output: "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]);
// Array [ "football", "foosball" ]</pre>
<p>如果没有 <code>/g</code> 标志,<code>matchAll</code> 会抛出异常。</p>
<pre class="brush: js">const regexp = RegExp('[a-c]','');
const str = 'abc';
Array.from(str.matchAll(regexp), m => m[0]);
// TypeError: String.prototype.matchAll called with a non-global RegExp argument</pre>
<p><code>matchAll</code> 内部做了一个 regexp 的复制,所以不像 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec">regexp.exec</a>, <code>lastIndex</code> 在字符串扫描时不会改变。</p>
<pre class="brush: js">const regexp = RegExp('[a-c]','g');
regexp.lastIndex = 1;
const str = 'abc';
Array.from(str.matchAll(regexp), m => `${regexp.lastIndex} ${m[0]}`);
// Array [ "1 b", "1 c" ]
</pre>
<h3 id="捕获组的更佳途径">捕获组的更佳途径</h3>
<p><code>matchAll</code> 的另外一个亮点是更好地获取捕获组。因为当使用 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match">match()</a></code> 和 <code>/g</code> 标志方式获取匹配信息时,捕获组会被忽略:</p>
<pre class="brush: js">var regexp = /t(e)(st(\d?))/g;
var str = 'test1test2';
str.match(regexp);
// Array ['test1', 'test2']</pre>
<p>使用 <code>matchAll</code> 可以通过如下方式获取分组捕获:</p>
<pre class="brush: js">let 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]
</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-string.prototype.matchall', 'String.prototype.matchAll')}}</td>
<td>{{Spec2('ESDraft')}}</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("javascript.builtins.String.matchAll")}}</p>
<h2 id="相关链接">相关链接</h2>
<ul>
<li>{{jsxref("RegExp")}}</li>
<li>{{jsxref("RegExp.prototype.exec()")}}</li>
<li>{{jsxref("RegExp.prototype.test()")}}</li>
</ul>
|