字符串的replace()方法隐藏着什么不可告人秘密?

最近在做JS算法项目时发现一个令我匪夷所思的问题, 这里想记录一下问题。

首先介绍一下字符串replace()方法的基本用法。

replace() 方法使用一个替换值(replacement)替换掉一个匹配模式(pattern)在原字符串中某些或所有的匹配项,并返回替换后的字符串。这个替换模式可以是字符串或者RegExp(正则表达式),替换值可以是一个字符串或者一个函数。

语法EDIT

str.replace(regexp|substrnewSubStr|function[, flags])

参数

regexp
一个 RegExp 对象。该正则所匹配的内容会被第二个参数的返回值替换掉。
substr
一个要被 newSubStr 替换的字符串。
newSubStr
替换掉第一个参数在原字符串中的匹配部分。该字符串中可以内插一些特殊的变量名。
function

一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。该函数的参数描述请参考 指定一个函数作为参数 小节。

返回值

一个部分或全部匹配由替代模式所取代的新的字符串。

关于这个方法具体的信息参考MDN再好不过了。

String.prototype.replace() - JavaScript | MDN

现在有一个非常简单的需求:将HTML代码中的特殊字符进行实体转义:

先看一个简单的输出没有错误的版本:

正确方法一:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

function convertHTML(str) {

  // :)

  var pattern=/[&<>"‘]/g;

  return str.replace(pattern,function(match){

    switch(match){

        case "<":

        return "&lt;";

        case ">":

        return "&gt;";

        case "&":

        return "&amp;";

        case "\"":

        return "&quot;";

        case "\‘":

        return "&apos;";

    }

  });

}

console.log(convertHTML("<Tom & Jerry>"));//&lt;Tom &amp; Jerry&gt;

指定一个函数作为第二个参数。在这种情况下,当匹配执行后, 该函数就会执行。 函数的返回值作为替换字符串。 (注意:  上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是, 如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么这个方法将被多次调用, 每次匹配都会被调用。

后来我对上述的代码进行了改造,使代码看起来更明了:

正确方法二:


1

2

3

4

5

6

7

8

9

10

11

12

13

function convertHTML(str) {

  // &colon;&rpar;

  var pattern=/[&<>"‘]/g;

  rules={"&":"&amp;","<":"&lt;",">":"&gt;",‘"‘:"&quot;","‘":"&apos;"};

 return str.replace(pattern,function(match){

    return  rules[match];

  });

}

console.log(convertHTML("<Tom & Jerry>"));//&lt;Tom &amp; Jerry&gt;

很明显非常简单的一个改造,我将规则键值对放在了rules对象中,输出结果同样也是正确的。

接下来,我发现貌似使用RegExp构造函数属性还能使代码变得更加简单。RegExp构造函数属性如下表所示:

其中一个叫做lastMatch的属性深深吸引了我。我在想能不能像下面这样改造一下:

错误方法:


1

2

3

4

5

6

function convertHTML(str) {

  var pattern=/[&<>"‘]/g;

  rules={"&":"&amp;","<":"&lt;",">":"&gt;",‘"‘:"&quot;","‘":"&apos;"};

  return str.replace(pattern,rules[RegExp.lastMatch]);

}

console.log(convertHTML("<Tom & Jerry>"));

写完这个代码,突然觉得自己聪明绝世,飘飘然了呢,然而一瓢冷水泼下来了。运行结果如下:


1

undefinedTom undefined Jerryundefined

这是什么鬼,貌似该替换的字符都被替换成了undefined。接下来我加入了一条测试语句:


1

2

3

4

5

6

7

8

9

function convertHTML(str) {

  // &colon;&rpar;

  var pattern=/[&<>"‘]/g;

  rules={"&":"&amp;","<":"&lt;",">":"&gt;",‘"‘:"&quot;","‘":"&apos;"};

  var result=str.replace(pattern,rules[RegExp.lastMatch]);

//下面是测试代码

  console.log(RegExp.lastMatch);//>

  return result;

}

console.log(convertHTML("<Tom & Jerry>"));

根据测试代码,最后匹配的是“>”说明匹配是正确的,但是最后为什么没有按照规则进行替换呢,我想应该是replace()方法的实现机制我们没有弄清楚,网上没有找到相关的资料,所以只能提醒自己以后不能写这样的代码了,在这种情况下,还是乖乖函数作为第二个参数。。。。。。等等,用函数做第二个参数,我又进行了下面的修改:


1

2

3

4

5

6

7

8

9

10

function convertHTML(str) {

  // &colon;&rpar;

  var pattern=/[&<>"‘]/g;

  rules={"&":"&amp;","<":"&lt;",">":"&gt;",‘"‘:"&quot;","‘":"&apos;"};

  var result=str.replace(pattern,function(){

    return rules[RegExp.lastMatch]

  });

  return result;

}

console.log(convertHTML("<Tom & Jerry>"));//&lt;Tom &amp; Jerry&gt;

注意上面我还是使用了正则表达式函数属性与方法二是有区别的,但是结果却是离奇的正确了。(难道闭包作怪)

replace()究竟隐藏着什么秘密,还有待挖掘??

来自为知笔记(Wiz)

时间: 2024-10-11 17:13:30

字符串的replace()方法隐藏着什么不可告人秘密?的相关文章

C#自定义字符串替换Replace方法实例

本文实例讲述了C#自定义字符串替换Replace方法.分享给大家供大家参考.具体实现方法如下: 一.问题: 前一阵遇到一个如标题的算法题,是将原有字符串的某些片段替换成指定的新字符串片段,例如将源字符串:abcdeabcdfbcdefg中的cde替换成12345,得到结果字符串:ab12345abcdfb12345fg,即:abcdeabcdfbcdefg -> ab12345abcdfb12345fg. 二.实现方法: 显然不能用string.Replace方法,需要自定义一个方法 strin

C#自定义字符串替换Replace方法

前一阵遇到一个如标题的算法题,是将原有字符串的某些片段替换成指定的新字符串片段,例如将源字符串:abcdeabcdfbcdefg中的cde替换成12345,得到结果字符串:ab12345abcdfb12345fg,即:abcdeabcdfbcdefg -> ab12345abcdfb12345fg. 显然不能用string.Replace方法,需要自定义一个方法 string Replace(string originalString, string strToBeReplaced, strin

js 字符串的replace() 方法和实现replaceAll() 方法

一.js中字符串的替换使用replace() 方法,但它只替换第一个匹配子串.如下例: <script type="text/javascript"> var sourceString = "我是被替换的字符串,是被替换的哦"; var replaceString = sourceString.replace("替换", "replace"); alert(replaceString); // 我是被replace

JS replace()方法-字符串首字母大写

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. replace()方法有两个参数,第一个参数是正则表达式,正则表达式如果带全局标志/g,则是代表替换所有匹配的字符串,否则是只替换第一个匹配串.第二个参数可以是字符串,也可以是函数.$1.$2...表示与正则表达式匹配的文本. There are many ways we can make a difference. Global change starts with you. Sign up f

js中替换字符串(replace方法最简单的应用)

replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(string),reExp可以是正则表达式对象(RegExp)也可以是字符串(string),replaceText是替代查找到的字符串. 首先获取时间控件的值:"2017-06-12"  接口参数需要时间格式为:"2017.06.17"  此时.replace("-",".")只是把第一个&

JS使用replace()方法和正则表达式进行字符串的搜索与替换实例

1.JS字符串的替换及replace()方法的使用 replace(regexp,replacement)方法有两个参数,第一参数可以是一个纯文本字符串或是一个RegExp对象,具体请看RegExp对象的使用:第二个参数可是一个字符串也可以是一个函数. 以下是JS字符串替换的举例: 例1: var str="Hello world!"; document.write(str.replace(/world/, "phper")); 例2: var reg=new Re

字符串中的replace方法

String.prototype.replace() 该方法作为字符串中非常常用的方法, 今天我们具体介绍一下它的用法 语法格式 someString.replace(regxp | substr, newStr | function) 第一个入参可以是正则或者是字符串, 如是字符串将不能设置忽略大小写, 在匹配到结果后返回, 而不继续匹配下去, 若是正则表达式则会按正则的意图进行匹配; 第二个入参是新字符串或者是回调函数, 若是新字符串则会替换匹配到的字符串, 如果是函数则在每次匹配到结果时执

常用字符串、数组方法总结

一.字符串方法 1.charAt方法返回指定索引位置处的字符.如果超出有效范围的索引值返回空字符串 strObj.charAt(index) 说明: index为要得到的字符基于零的索引.有效值是0与字符串长度减一之间的值. 例如: var str = "ABC"; str.charAt(1) // Bstr.charAt(3) // '' 2.slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分 注意:slice()方法返回一个从 start 开始(包括 sta

7.python字符串-内置方法分析

上篇对python中的字符串进行了列举和简单说明,但这些方法太多,逐一背下效率实在太低,下面我来对这些方法安装其功能进行总结: 1.字母大小写相关(中文无效) 1.1 S.upper() -> string 返回一个字母全部大写的副本 1.2 S.lower() -> string 返回一个字母全是小写的副本 1.3 S.swapcase() -> string 返回一个字母大小写转换后的副本 1.4 S.title() -> string 将单词的首字母大写,即为所谓的标题 方框