-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path14-3.html
191 lines (180 loc) · 6.67 KB
/
14-3.html
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="./public/favicon.ico" />
<meta http-equiv="cache-control" content="no-cache" />
<title></title>
<link rel="stylesheet" href=" https://necolas.github.io/normalize.css/8.0.1/normalize.css" />
<link rel="stylesheet" href="./hightlight/default.min.css" />
<link rel="stylesheet" href="./css/main.css" />
<link rel="stylesheet" href="./css/copybutton.css" />
<link rel="stylesheet" href="./css/hightlight.css" />
<script src="./hightlight/hightlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-BEVZJDBC7Z"></script>
<script src="./js/gtag.js"></script>
</head>
<body>
<header>
<nav>
<h1>
<span id="toggle-menu"></span>
<a href="index.html"></a>
</h1>
</nav>
</header>
<main>
<aside>
<nav></nav>
</aside>
<article>
<h2 id="14-3">14-3 String.prototype.matchAll()</h2>
<p>
matchAll()
方法回傳一個疊代器,該疊代器包含了檢索字串與正則表達式進行匹配的所有結果(包括捕獲組)。
</p>
<p>
一個匹配結果的可疊代疊代器物件(它不可重新開始)。每個匹配結果都是一個陣列,其形狀與
RegExp.prototype.exec() 的回傳值相同。
</p>
<pre><code class="language-js">
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"]
</code></pre>
<h3>語法</h3>
<p>matchAll(regexp)</p>
<h4>
參數
<strong>regexp</strong>
規則
</h4>
<p>
一個正則表達式物件,或者是任何具有 Symbol.matchAll 方法的物件。如果 regexp 不是一個 RegExp
物件,並且沒有 Symbol.matchAll 方法,它將通過 new RegExp(regexp, 'g') 被隱式轉換為一個
RegExp 物件。如果 regexp 是一個正則表達式,那麽它必須設置了全域(g)標志,否則會拋出
TypeError 異常。
</p>
<p>Regexp.prototype.exec() 和 matchAll()</p>
<p>
如果沒有 matchAll() 方法,仍然可以使用帶有 g 標志的正則表達式調用 regexp.exec()
來在迴圈中獲取所有匹配結果:
</p>
<pre><code class="language-js">
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。
</code></pre>
<p>
如果有 matchAll() 方法,則可以避免使用 while 迴圈和帶有 g 標志的
exec。相反,你可以獲得一個疊代器,以便使用更方便的 for...of 迴圈、陣列展開語法或
Array.from() 構造函數:
</p>
<pre><code class="language-js">
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" ]
</code></pre>
<p>如果沒有 g 標志, matchAll 會拋出異常。</p>
<pre><code class="language-js">
const regexp = /[a-c]/;
const str = "abc";
str.matchAll(regexp);
// TypeError
</code></pre>
<p>
matchAll 內部做了一個 regexp 的複製,所以不像 regexp.exec() , lastIndex
在字串掃描後不會改變。
</p>
<pre><code class="language-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" ]
</code></pre>
<p>
然這也意味著,與在迴圈中使用 regexp.exec() 不同,你不能更改 lastIndex
來使正則表達式前進或倒退。
</p>
<h3>
比
<code>String.prototype.match()</code>
更好的捕獲組獲取方式
</h3>
<p>
matchAll() 方法的另一個重要優點是改進了對於捕獲組的獲取方式。當使用全域 g 標志調用 match()
方法時,捕獲組會被忽略:
</p>
<pre><code class="language-js">
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";
str.match(regexp); // ['test1', 'test2']
</code></pre>
<p>使用 matchAll 方法,可以輕松獲取捕獲組:</p>
<pre><code class="language-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]
</code></pre>
<h3>使用實現了 @@matchAll 的非正則物件調用 matchAll()</h3>
<p>
如果一個物件有一個 Symbol.matchAll 方法, 它可以被用作自定義匹配器。Symbol.matchAll
的回傳值將成為 matchAll() 的回傳值。
</p>
<pre><code class="language-js">
const str = "Hmm, this is interesting.";
str.matchAll({
[Symbol.matchAll](str) {
return [["Yes, it's interesting."]];
},
}); // returns [["Yes, it's interesting."]]
</code></pre>
<p>資料來源:</p>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll"
>
https://developer.mozilla.org/.../matchAll
</a>
</p>
<p>
<a href="https://www.youtube.com/watch?v=3IbCKkrjZog">
https://www.youtube.com/watch?v=3IbCKkrjZog
</a>
</p>
</article>
</main>
</body>
<script type="module" src="./js/main.js"></script>
</html>