字符串的replace()方法隐藏着什么不可告人秘密?
最近在做JS算法项目时发现一个令我匪夷所思的问题, 这里想记录一下问题。
首先介绍一下字符串replace()方法的基本用法。
replace() 方法使用一个替换值(replacement)替换掉一个匹配模式(pattern)在原字符串中某些或所有的匹配项,并返回替换后的字符串。这个替换模式可以是字符串或者RegExp
(正则表达式),替换值可以是一个字符串或者一个函数。
语法EDIT
str.replace(regexp|substr, newSubStr|function[, flags])
参数
regexp
- 一个
RegExp
对象。该正则所匹配的内容会被第二个参数的返回值替换掉。
substr
- 一个要被
newSubStr
替换的字符串。
newSubStr
- 替换掉第一个参数在原字符串中的匹配部分。该字符串中可以内插一些特殊的变量名。
function
一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。该函数的参数描述请参考 指定一个函数作为参数 小节。
返回值
一个部分或全部匹配由替代模式所取代的新的字符串。
关于这个方法具体的信息参考MDN再好不过了。
String.prototype.replace() - JavaScript | MDN
现在有一个非常简单的需求:将HTML代码中的特殊字符进行实体转义:
先看一个简单的输出没有错误的版本:
正确方法一:
12345678910111213141516171819function
convertHTML(str) {
// :)
var
pattern=/[&<>
"']/g;
return str.replace(pattern,function(match){
switch(match){
case "
<
":
return "
<
";
case "
>
":
return "
>
";
case "
&
":
return "
&
";
case "
\
""
:
return
"""
;
case
"\'"
:
return
"'"
;
}
});
}
console.log(convertHTML(
"<Tom & Jerry>"
));//<Tom & Jerry>
指定一个函数作为第二个参数。在这种情况下,当匹配执行后, 该函数就会执行。 函数的返回值作为替换字符串。 (注意: 上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是, 如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么这个方法将被多次调用, 每次匹配都会被调用。
后来我对上述的代码进行了改造,使代码看起来更明了:
正确方法二:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function convertHTML(str) { // :) var pattern=/[&<> "']/g; rules={" & ":" & "," < ":" < "," > ":" > ",'" ':""","' ": "'" }; return str.replace(pattern, function (match){ return rules[match]; }); } console.log(convertHTML( "<Tom & Jerry>" ));//<Tom & Jerry> |
很明显非常简单的一个改造,我将规则键值对放在了rules对象中,输出结果同样也是正确的。
接下来,我发现貌似使用RegExp构造函数属性还能使代码变得更加简单。RegExp构造函数属性如下表所示:
其中一个叫做lastMatch的属性深深吸引了我。我在想能不能像下面这样改造一下:
错误方法:
1
2
3
4
5
6
|
function convertHTML(str) { var pattern=/[&<> "']/g; rules={" & ":" & "," < ":" < "," > ":" > ",'" ':""","' ": "'" }; 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) { // :) var pattern=/[&<> "']/g; rules={" & ":" & "," < ":" < "," > ":" > ",'" ':""","' ": "'" };
//下面是测试代码 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) { // :) var pattern=/[&<> "']/g; rules={" & ":" & "," < ":" < "," > ":" > ",'" ':""","' ": "'" }; var result=str.replace(pattern, function (){ return rules[RegExp.lastMatch] }); return result; } console.log(convertHTML( "<Tom & Jerry>" )); //<Tom & Jerry> |
注意上面我还是使用了正则表达式函数属性与方法二是有区别的,但是结果却是离奇的正确了。(难道闭包作怪)
replace()究竟隐藏着什么秘密,还有待挖掘??
字符串的replace()方法隐藏着什么不可告人秘密?的更多相关文章
- js中字符串的replace方法区分单双引号
今天遇到一问题,js文件中调用字符串的replace方法,不起作用. 后来排查可能觉得replace("<option value='1'>admin</option&g ...
- 浅谈JavaScript的字符串的replace方法
JavaScript字符串提供了一个replace方法.replace方法可以接受两个参数:第一个参数可以使RegExp对象或者一个字符串,第二个参数可以是一个字符串或者一个函数.如果第一个参数是字符 ...
- 字符串替换replace方法
字符串替换replace方法: http://www.w3school.com.cn/jsref/jsref_replace.asp http://www.cnblogs.com/skywang/ar ...
- C#自定义字符串替换Replace方法
前一阵遇到一个如标题的算法题,是将原有字符串的某些片段替换成指定的新字符串片段,例如将源字符串:abcdeabcdfbcdefg中的cde替换成12345,得到结果字符串:ab12345abcdfb1 ...
- JQuery字符串替换replace方法
在日常的js开发中,常常会用到JQuery, 当要把字符串中的内容替换时,如果使用类似C#的string.replace方法,如下 var str='aabbccaa'; str=str.replac ...
- js 字符串的replace() 方法和实现replaceAll() 方法
一.js中字符串的替换使用replace() 方法,但它只替换第一个匹配子串.如下例: <script type="text/javascript"> var sour ...
- JavaScript字符串替换replace方法
在日常的js开发中, 当要把字符串中的内容替换时,如果使用类似C#的string.replace方法,如下 var str='aabbccaa'; str=str.replace('aa','dd') ...
- 字符串函数 replace() 方法妙用
alert('10 12 14 16'.replace(/d+/g,function(match){ return parseInt(match,10) > 10 ? '*' : match; ...
- 【转载】C#中string类使用Replace方法来替换字符串
在C#的字符串操作过程中,有时候需要替换字符串中的某个子字符串,此时就可以使用到字符串类自带的Replace方法来实现,Replace方法将查找到所有符合被替换的子字符串,然后将之全部替换为目标字符串 ...
随机推荐
- AutoVFL(适配)
1.添加约束(系统) a.一个约束(上下左右) +(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)att ...
- 测试dns
测试dns nslookup test.cn 10.109.68.114 ipconfig /flushdns dig test.cn @10.109.68.114 sudo /etc/init.d/ ...
- 正则表达式之g标志,match和 exec
1.g标志 g标志一般是与match和exec来连用,否则g标志没有太大的意义. 先来看一个带g标志的例子: var str = "tankZHang (231144) tank yi ...
- html5中常见的全局属性
1.contentEditable属性 1.功能说明 (1)功能:允许用户编辑元素中的内容 (2)说明:是一个布尔值,false是不能编辑,true为可编辑 该元素还隐藏一个inherit状态 也是 ...
- VBA笔记(二)——基础语法
数据类型 VBA提供了15种标准数据类型,具体见下表: 变量 Sub 变量学习() 'Dim 变量名 As 数据类型 Dim str1 As String '声明定长的String变量 '使用变量类型 ...
- bzoj1003 物流运输
Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...
- STM32f103之外部中断
一.背景 有个需求,IO口检测上升沿,然后做相应的动作.在此记录STM32F103的外部中断结构及配置方法, 以备下次快速上手使用. 有许多不太明白,又是老司机(:-D)帮忙,真的是站在别人的肩膀上会 ...
- PHP合并2个数字键数组的值
先要了解一个基础知识点:PHP数组合并+与array_merge的区别分析 & 对多个数组合并去重技巧 <?php /** * PHP合并2个数字键数组的值 * * @param arr ...
- MySQL 的 find_in_set 函数使用方法
举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文...1,12,13 等等 . 现在有篇文章他既是 头条,又是热点,还是图文, type中以 1, ...
- Ubuntu 14.04 LTS 安装Docker
Docker官方是有很详细的安装文档(https://docs.docker.com/engine/installation/ubuntulinux/),这里做了一个Ubuntu 14.04 LTS中 ...