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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
---
title: String.prototype.replace()
slug: Web/JavaScript/Reference/Global_Objects/String/replace
tags:
- JavaScript
- Method
- Prototype
- Regular
- String
translation_of: Web/JavaScript/Reference/Global_Objects/String/replace
---
<div>{{JSRef}}</div>
<p><strong><code>replace()</code></strong> 方法返回一个由替换值(<code>replacement</code>)替换部分或所有的模式(<code>pattern</code>)匹配项后的新字符串。模式可以是一个字符串或者一个<a href="/zh-CN/docs/Web/JavaScript/Reference/RegExp">正则表达式</a>,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。<strong>如果<code>pattern</code>是字符串,则仅替换第一个匹配项。</strong></p>
<p>原字符串不会改变。</p>
<div>{{EmbedInteractiveExample("pages/js/string-replace.html")}}</div>
<h2 id="语法">语法</h2>
<pre class="syntaxbox notranslate"><code><var>str</var>.replace(<var>regexp</var>|<var>substr</var>, <var>newSubStr</var>|<var>function</var>)</code></pre>
<h3 id="参数">参数</h3>
<dl>
<dt><code>regexp </code>(pattern)</dt>
<dd>一个{{jsxref("RegExp")}} 对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。</dd>
</dl>
<dl>
<dt><code>substr </code>(pattern)</dt>
<dd>一个将被 <code>newSubStr</code> 替换的 {{jsxref("String","字符串")}}。其被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换。</dd>
</dl>
<dl>
<dt><code>newSubStr</code> (replacement)</dt>
<dd>用于替换掉第一个参数在原字符串中的匹配部分的{{jsxref("String", "字符串")}}。该字符串中可以内插一些特殊的变量名。参考下面的<a href="#使用字符串作为参数">使用字符串作为参数</a>。</dd>
</dl>
<dl>
<dt><code>function</code> (replacement)</dt>
<dd>一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。参考下面的<a href="#指定一个函数作为参数">指定一个函数作为参数</a>。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<p>一个部分或全部匹配由替代模式所取代的新的字符串。</p>
<h2 id="描述">描述</h2>
<p>该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。</p>
<p>在进行全局的搜索替换时,正则表达式需包含 <code>g</code> 标志。</p>
<h3 id="使用字符串作为参数">使用字符串作为参数</h3>
<p>替换字符串可以插入下面的特殊变量名:</p>
<table class="fullwidth-table">
<tbody>
<tr>
<td class="header">变量名</td>
<td class="header">代表的值</td>
</tr>
<tr>
<td><code>$$</code></td>
<td>插入一个 "$"。</td>
</tr>
<tr>
<td><code>$&</code></td>
<td>插入匹配的子串。</td>
</tr>
<tr>
<td><code>$`</code></td>
<td>插入当前匹配的子串左边的内容。</td>
</tr>
<tr>
<td><code>$'</code></td>
<td>插入当前匹配的子串右边的内容。</td>
</tr>
<tr>
<td style="white-space: nowrap;"><code>$<em>n</em></code></td>
<td>
<p>假如第一个参数是 {{jsxref("RegExp")}}对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始。如果不存在第 n个分组,那么将会把匹配到到内容替换为字面量。比如不存在第3个分组,就会用“$3”替换匹配到的内容。</p>
</td>
</tr>
<tr>
<td style="white-space: nowrap;"><code><em>$<Name></em></code></td>
<td> 这里<em><code>Name</code></em> 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),这个变量将被处理为空字符串。只有在支持命名分组捕获的浏览器中才能使用。</td>
</tr>
</tbody>
</table>
<h3 id="指定一个函数作为参数">指定一个函数作为参数</h3>
<p>你可以指定一个函数作为第二个参数。在这种情况下,当匹配执行后,该函数就会执行。 函数的返回值作为替换字符串。 (注意:上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是,如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。</p>
<p>下面是该函数的参数:</p>
<table class="fullwidth-table">
<tbody>
<tr>
<td class="header">变量名</td>
<td class="header">代表的值</td>
</tr>
<tr>
<td><code>match</code></td>
<td>匹配的子串。(对应于上述的$&。)</td>
</tr>
<tr>
<td><code>p1,p2, ...</code></td>
<td>
<p>假如replace()方法的第一个参数是一个{{jsxref("RegExp")}} 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)例如,如果是用 <code>/(\a+)(\b+)/</code> 这个来匹配,<code>p1</code> 就是匹配的 <code>\a+</code>,<code>p2</code> 就是匹配的 <code>\b+</code>。</p>
</td>
</tr>
<tr>
<td><code>offset</code></td>
<td>
<p>匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 <code>'abcd'</code>,匹配到的子字符串是 <code>'bc'</code>,那么这个参数将会是 1)</p>
</td>
</tr>
<tr>
<td><code>string</code></td>
<td>被匹配的原字符串。</td>
</tr>
<tr>
<td>NamedCaptureGroup</td>
<td>命名捕获组匹配的对象</td>
</tr>
</tbody>
</table>
<p>(精确的参数个数依赖于 <code>replace()</code> 的第一个参数是否是一个正则表达式({{jsxref("RegExp")}})对象,以及这个正则表达式中指定了多少个括号子串,如果这个正则表达式里使用了命名捕获, 还会添加一个命名捕获的对象)</p>
<p>下面的例子将会使 <code>newString</code> 变成 <code>'abc - 12345 - #$*%'</code>:</p>
<pre class="brush: js notranslate">function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%
</pre>
<h2 id="Examples" name="Examples">示例</h2>
<h3 id="在_replace_中使用正则表达式">在 <code>replace()</code> 中使用正则表达式</h3>
<p>在下面的例子中,<code>replace()</code> 中使用了正则表达式及忽略大小写标示。</p>
<pre class="brush: js notranslate">var str = 'Twas the night before Xmas...';
var newstr = str.replace(/xmas/i, 'Christmas');
console.log(newstr); // Twas the night before Christmas...
</pre>
<h3 id="在_replace_中使用_global_和_ignore_选项">在 <code>replace()</code> 中使用 <code>global</code> 和 <code>ignore</code> 选项</h3>
<p>下面的例子中,正则表达式包含有全局替换(g)和忽略大小写(i)的选项,这使得replace方法用'oranges'替换掉了所有出现的"apples".</p>
<pre class="brush: js notranslate">var re = /apples/gi;
var str = "Apples are round, and apples are juicy.";
var newstr = str.replace(re, "oranges");
// oranges are round, and oranges are juicy.
console.log(newstr);
</pre>
<h3 id="交换字符串中的两个单词">交换字符串中的两个单词</h3>
<p>下面的例子演示了如何交换一个字符串中两个单词的位置,这个脚本使用$1 和 $2 代替替换文本。</p>
<pre class="brush: js notranslate">var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
// Smith, John
console.log(newstr);
</pre>
<h3 id="使用行内函数来修改匹配到的字符。">使用行内函数来修改匹配到的字符。</h3>
<p>在这个例子中,所有出现的大写字母转换为小写,并且在匹配位置前加一个连字符。重要的是,在返回一个替换了的字符串前,在匹配元素前进行添加操作是必要的。</p>
<p>在返回前,替换函数允许匹配片段作为参数,并且将它和连字符进行连接作为新的片段。</p>
<pre class="brush: js notranslate">function styleHyphenFormat(propertyName) {
function upperToHyphenLower(match) {
return '-' + match.toLowerCase();
}
return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}
</pre>
<p>运行 <code>styleHyphenFormat('borderTop')</code><code>,</code><span>将</span><span>返回 'border-top'。</span></p>
<p>因为我们想在最终的替换中进一步转变匹配结果,所以我们必须使用一个函数。这迫使我们在使用{{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}}方法前进行评估。如果我们尝试不用一个函数进行匹配,那么使用{{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} 方法将不会有效。</p>
<pre class="brush: js notranslate">var newString = propertyName.replace(/[A-Z]/g, '-' + '$&'.toLowerCase()); // won't work
</pre>
<p>这是因为 <code>'$&'.toLowerCase()</code> 会先被解析成字符串字面量(这会导致相同的'$&')而不是当作一个模式。</p>
<h3 id="将华氏温度转换为对等的摄氏温度">将华氏温度转换为对等的摄氏温度</h3>
<p>下面的例子演示如何将华氏温度转换为对等的摄氏温度。华氏温度用一个数字加一个"F"来表示,这个函数将返回一个数字加"C"来表示的摄氏温度。例如,如果输入是 212F,这个函数将返回 100C。如果输入的数字是 0F,这个方法将返回 "-17.77777777777778C"。</p>
<p>正则表达式test检查任何数字是否以 F 结尾。华氏温度通过第二个参数p1进入函数。这个函数基于华氏温度作为字符串传递给f2c函数设置成摄氏温度。然后f2c()返回摄氏温度。这个函数与Perl的 s///e 标志相似。</p>
<pre class="brush: js notranslate">function f2c(x)
{
function convert(str, p1, offset, s)
{
return ((p1-32) * 5/9) + "C";
}
var s = String(x);
var test = /(\d+(?:\.\d*)?)F\b/g;
return s.replace(test, convert);
}
</pre>
<h3 id="使用行内函数和正则来避免循环">使用行内函数和正则来避免循环</h3>
<p>下例把某种模式的字符串转换为一个对象数组(其元素为对象)。</p>
<p><strong>输入:</strong><br>
一个由 x,- 和 _ 组成的字符串。</p>
<pre class="notranslate">x-x_
---x---x---x---
-xxx-xx-x-
_x_x___x___x___
</pre>
<p><strong>输出:</strong></p>
<p>一个数组对象。'x' 产生一个 'on' 状态,'-'(连接符)产生一个 'off' 状态,而 '_' (下划线)表示 'on' 状态的长度。</p>
<pre class="brush: js notranslate">[
{ on: true, length: 1 },
{ on: false, length: 1 },
{ on: true, length: 2 }
...
]</pre>
<p>代码片段:</p>
<pre class="brush: js notranslate">var str = 'x-x_';
var retArr = [];
str.replace(/(x_*)|(-)/g, function(match, p1, p2) {
if (p1) { retArr.push({ on: true, length: p1.length }); }
if (p2) { retArr.push({ on: false, length: 1 }); }
});
console.log(retArr);</pre>
<p>该代码片段生成了一个数组,包含三个期望格式的对象,避免了使用 for 循环语句。</p>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES3')}}</td>
<td>{{Spec2('ES3')}}</td>
<td>Initial definition. Implemented in JavaScript 1.2.</td>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-15.5.4.11', 'String.prototype.replace')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-string.prototype.replace', 'String.prototype.replace')}}</td>
<td>{{Spec2('ES6')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-string.prototype.replace', 'String.prototype.replace')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p class="hidden">The compatibility table in 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.replace")}}</p>
<h3 id="Firefox_备注">Firefox 备注</h3>
<ul>
<li><code>flags</code> 是一个仅在 Gecko 中可用的非标准的第三方参数:<code><var>str</var>.replace(<var>regexp</var>|<var>substr</var>, <var>newSubStr</var>|<var>function, flags</var>)</code></li>
<li>从 Gecko 27 {{geckoRelease(27)}} 开始,这个方法就被整合到了ECMAScript规范中。当 replace() 被使用全局 g 标志的正则表达式调用时,{{jsxref("RegExp.lastIndex")}} 属性将被重置为 0({{bug(501739)}})。</li>
<li>从 Gecko 39 {{geckoRelease(39)}} 开始,<code>flags</code> 参数便被弃用,且在调用时会抛出一个控制台警告({{bug(1142351)}})。</li>
<li>从 Gecko 47 {{geckoRelease(47)}} 开始,在非发行版本中已不再支持非标准的 <code>flags</code> 参数,并且不久后会完全移除该参数({{bug(1245801)}})。</li>
<li>从 Gecko 49 {{geckoRelease(49)}} 开始,不再支持非标准的 <code>flags</code> 参数({{bug(1108382)}})。</li>
</ul>
<h2 id="参见">参见</h2>
<ul>
<li>{{jsxref("String.prototype.match()")}}</li>
<li>{{jsxref("RegExp.prototype.exec()")}}</li>
<li>{{jsxref("RegExp.prototype.test()")}}</li>
</ul>
|