跳到主要内容

String API

replace

考虑下面的代码执行结果是什么?

'a.b.c'.replace(/(.)\.(.)\.(.)/, '$2.$1.$0');
  1. cba
  2. c.b.a
  3. ...
  4. b.a.$0

答案:第四个选项正确。

💡 解析

要做出来这道题目,需要先了解 replace 这个函数。replace 函数非常强大,它是用来匹配特定的字符串或正则表达式,然后把匹配到的结果替换成新的字符串的函数。一般我们使用 replace 时第一个参数是一个字符串或者正则表达式,第二个参数是一个字符串:

// 当第一个参数是字符串时,仅第一个匹配项会被替换。
"abcdcba".replace("a", "y"); // ybcdcba
// 正则表达式中的 g 参数表示全局匹配,有了它,所有匹配项都会被代替
"abcdcba".replace(/a/g, "y"); // ybcdcby

上面用法很常见。在正则表达式中你是否见过这样的表达式:

'abcdabc'.match(/^(\w+)\w*\1$/);

上面会匹配到。而且匹配到了两个。一个是全局的匹配字符,另一个是捕获(括号里的内容 abc)。在这个正则表达式里 \1 是一个 反向引用,指向正则表达式中第 n 个括号(从左开始数)中匹配的子字符串。

replace 函数中,第二个参数可以插入下面的特殊变量名作为参数:

变量名代表的值
$$插入一个 "$"
$&插入匹配的子串
$`插入当前匹配的子串左边的内容
$'插入当前匹配的子串右边的内容
$n假如第一个参数是 RegExp 对象,并且 n 是个小于 100 的非负整数,那么插入第 n 个括号匹配的字符串,索引是从 1 开始

replace 中的 $n 与正则表达式中的反向引用有些相似,而且都是 n 都是从 1 开始。因此上面的代码 '$2.$1.$0' 中的 $0 是没有意义的(一个普通的字符串)。$2 表示第左起二个括号,$1 表示左起第一个括号。于是被替换成了 b.a.$0

拓展replace 函数的第二个参数可以是一个函数。

当第二个参数是一个函数时,当匹配执行后,该函数就会执行。函数的返回值作为替换字符串。另外要注意的是,如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。这个函数有多个参数:

变量名描述
match匹配的子串(对应于上述的 $&
p1,p2, ...假如 replace() 方法的第一个参数是一个 RegExp 对象,则代表第 n 个括号匹配的字符串。(对应于上述的$1,$2等。)
offset匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 'abcd',匹配到的子字符串是 'bc',那么这个参数将会是 1)
string被匹配的原字符串

下面的函数将所有出现的大写字母转换为小写,并且在匹配位置前加一个连字符(-)。

function styleHyphenFormat(propertyName){
function upperToHyphenLower(match) {
return '-' + match.toLowerCase();
}
return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}

比如字符串是 borderTop,替换后将变成 border-top