diff options
Diffstat (limited to 'files/zh-cn/web/javascript/reference/global_objects/string/matchall/index.html')
-rw-r--r-- | files/zh-cn/web/javascript/reference/global_objects/string/matchall/index.html | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/files/zh-cn/web/javascript/reference/global_objects/string/matchall/index.html b/files/zh-cn/web/javascript/reference/global_objects/string/matchall/index.html new file mode 100644 index 0000000000..5fd54c46aa --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/string/matchall/index.html @@ -0,0 +1,135 @@ +--- +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 notranslate"><var>str</var>.matchAll(<var>regexp</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>regexp</code></dt> +</dl> + +<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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> + +<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> |