字符串的replace方法应用浅析


Posted in Javascript onDecember 06, 2011

这两个参数都是必须的,replace() 方法的参数 replacement 可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。对于replacement是函数的情况,给我们提供了很大的便利。

这有一个很简单的交换两个单词顺序的例子,如果不用repalce可以这么做:

(function(){ 
var str = 'click dblclick'; 
var result = str.split(/\b/).reverse().join('') 
console.log(result); 
})()

这么做略显麻烦,用replace处理则显得清爽许多:
(function(){ 
var str = 'click dblclick'; 
var result = str.replace(/\b(\w+)(\s+)(\w+)\b/,'$3$2$1'); 
console.log(result); 
})();

再看另一个例子——给数字加上千分位:
(function(){ 
var number = 12345678900; 
var result = (''+number).replace(/(\d)(?=(\d{3})+$)/g,'$1,'); 
console.log(result); 
})();

不过现在要扯的是replacement作为函数的用法,所以多此一举的把上面的形式改成函数的形式:

(function(){ 
var str = 'click dblclick'; 
var result = str.replace(/\b(\w+)(\s+)(\w+)\b/,function(all,$1,$2,$3){ 
return $3+$2+$1; 
}); 
console.log(result); 
})(); (function(){ 
var number = 12345678900; 
var result = (''+number).replace(/(\d)(?=(\d{3})+$)/g,function(all,$1){ 
return $1 + ','; 
}); 
console.log(result); 
})();

所以replace无非是捕获匹配的项然后经过处理,作为返回值进行替换,只不过是函数的比较给力。
下面看一个比较实用的例子,大多数语言都有的格式化输出,比如C语言的printf:
(function(){ 
var str = '%s may have gone, but there is a time of %s'; 
var result = str.replace(/(%s)/g,function(){ 
return 'replacement'; 
}) 
console.log(result); 
})()

这里有个问题就是,%s都是一样的,替换出来都是一样的,而且我们只能按照顺序来判断被替换的是哪一部分,如果添加一段,那么后面所有的都得变。所以我们得传个变量进去。
(function(){ 
var array = ['Swallows','return']; 
var i = 0; 
var str = '%s may have gone, but there is a time of %s'; 
var result = str.replace(/(%s)/g,function(){ 
return array[i++]; 
}) 
console.log(result); 
})(); 
(function(){ 
var str = '#{what} may have gone, but there is a time of #{how}'; 
var obj = { 
what : 'Swallows', 
how : 'return' 
} 
var result = str.replace(/(?:#{(\w+)})/g,function(all,$1){ 
return obj[$1]; 
}) 
console.log( result); 
})();

显然用对象的方法要靠谱一点。

同时,js并没有那么严格的类型要求,所以,%s这种形式也成为了局限。直接摈弃,换成我们容易理解的形式。

伪装成函数的样子就是:

(function(){ 
function gsub(str,replaceObj){ 
return str.replace(/(?:#{(\w+)})/g,function(all,$1){ 
return replaceObj[$1]; 
}) 
} 
console.log('gsub结果:',gsub('#{what} may have gone, but there is a time of #{how}',{ 
what : 'Swallows', 
how : 'return' 
})) 
})();

上面的gsub借用了Prototype中的gsub方法名字,虽然Prototype中的gsub并不是用的replace,但是形式上还是很像的。

现在面临的一个问题是:

#{what}这种形式的冲突问题,有可能字符串里面刚好就有这种形式的字符串,如果不作处理,后果大家都懂的。

第一种解决办法:正则里面有转义字符,我们也可以有,所以我们干脆在不需要的替换的部分前面加上'\'

第二种解决办法:让使用者自定义一个标志来替换#{}的标志,从而避免冲突。

看第一种方法:

(function(){ 
var str = '#{what} may have gone, but there is a time of #{how},\\#{reserve}'; 
function gsub(str,replaceObj){ 
return str.replace(/(^|.)(?:#{(\w+)})/g,function(all,$1,$2){ 
if($1 == '\\'){ 
return '#{' + $2 +'}'; 
} 
return $1 + replaceObj[$2]; 
}) 
} 
console.log('gsub结果:',gsub(str,{ 
what : 'Swallows', 
how : 'return' 
})) 
})();

上面需要注意的就是'\'在字符串中也是转义字符,写的时候也需要转义。

第二种方法:

我们把'#{what}'换成<%what%>的形式。

(function(){ 
function gsub(str,replaceObj,regexp){ 
regexp = regexp || /(?:#{(\w+)})/g; 
return str.replace(regexp,function(all,$1){ 
return replaceObj[$1]; 
}) 
} 
var str = '<%what%> may have gone, but there is a time of <%how%>,#{reserve}'; 
console.log('gsub结果:',gsub(str,{ 
what : 'Swallows', 
how : 'return' 
},/(?:<%(\w+)%>)/g)) 
})();

现在把gsub挂到String的原型上面
String.prototype.gsub = function(replaceObj,regexp){ 
regexp = regexp || /(^|.)(?:(#{)(\w+)(}))/g; 
return this.replace(regexp,function(all,$1,$2,$3,$4){ 
if($1 == '\\'){ 
return $2+$3+$4; 
} 
return $1 + replaceObj[$3] ; 
}) 
} 
var str = '<%what%> may have gone, but there is a time of <%how%>,\\<%how%>,#{how}'; 
var obj = { 
what : 'Swallows', 
how : 'return' 
} 
console.log('测试1:',str.gsub(obj,/(^|.)(?:(<%)(\w+)(%>))/g)); 
//Swallows may have gone, but there is a time of return,<%how%>,#{how} 
console.log('测试2:',str.gsub(obj)); 
//<%what%> may have gone, but there is a time of <%how%>,\<%how%>,return

嘿嘿,貌似和Prototype中的gsub很像了,不过Prototype中的gsub复杂一些,原理也不一致,熟悉一下,待会再仔细分析Prototype中的gsub方法。
Javascript 相关文章推荐
基于KMP算法JavaScript的实现方法分析
May 03 Javascript
javascript封装简单实现方法
Aug 11 Javascript
初步使用Node连接Mysql数据库
Mar 03 Javascript
AngularJS教程 ng-style 指令简单示例
Aug 03 Javascript
js日期相关函数dateAdd,dateDiff,dateFormat等介绍
Sep 24 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
Vue Ajax跨域请求实例详解
Jun 20 Javascript
JavaScript注册时密码强度校验代码
Jun 30 Javascript
JavaScript中in和hasOwnProperty区别详解
Aug 04 Javascript
使用JavaScript实现在页面中显示距离2017年中秋节的天数
Sep 26 Javascript
Vue 实现展开折叠效果的示例代码
Aug 27 Javascript
详解JavaScript中Arguments对象用途
Aug 30 Javascript
js滚动条回到顶部的代码
Dec 06 #Javascript
javascript检测浏览器flash版本的实现代码
Dec 06 #Javascript
javascript 随机展示头像实现代码
Dec 06 #Javascript
jQuery中需要注意的细节问题小结
Dec 06 #Javascript
jQuery load方法用法集锦
Dec 06 #Javascript
基于JQuery实现的类似购物商城的购物车
Dec 06 #Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
Dec 06 #Javascript
You might like
Zerg建筑一览
2020/03/14 星际争霸
外媒评选出10支2020年最受欢迎的Dota2战队
2021/03/05 DOTA
建立文件交换功能的脚本(二)
2006/10/09 PHP
探讨多键值cookie(php中cookie存取数组)的详解
2013/06/06 PHP
PHP在不同页面间传递Json数据示例代码
2013/06/08 PHP
PHP面向对象五大原则之依赖倒置原则(DIP)详解
2018/04/08 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
laravel orm 关联条件查询代码
2019/10/21 PHP
JavaScript 异步调用框架 (Part 1 - 问题 &amp; 场景)
2009/08/03 Javascript
js换图片效果可进行定时操作
2014/06/09 Javascript
使用Angular自定义字段校验指令的方法示例
2019/02/01 Javascript
vue2.0+vue-router构建一个简单的列表页的示例代码
2019/02/13 Javascript
非常漂亮的js烟花效果
2020/03/10 Javascript
[01:42]DOTA2 – 虚无之灵
2019/08/25 DOTA
Cpy和Python的效率对比
2015/03/20 Python
Python中的高级函数map/reduce使用实例
2015/04/13 Python
Python中处理字符串之isalpha()方法的使用
2015/05/18 Python
详解Python中open()函数指定文件打开方式的用法
2016/06/04 Python
老生常谈Python进阶之装饰器
2017/05/11 Python
python 多维切片之冒号和三个点的用法介绍
2018/04/19 Python
Python cv2 图像自适应灰度直方图均衡化处理方法
2018/12/07 Python
python实现统计文本中单词出现的频率详解
2019/05/20 Python
Win10+GPU版Pytorch1.1安装的安装步骤
2019/09/27 Python
PYTHON如何读取和写入EXCEL里面的数据
2019/10/28 Python
使用python-cv2实现视频的分解与合成的示例代码
2020/10/26 Python
HTML5 Canvas像素处理使用接口介绍
2012/12/02 HTML / CSS
将SVG图引入到HTML页面的实现
2019/09/20 HTML / CSS
JRE、JDK、JVM之间的关系怎样
2012/05/16 面试题
员工培训邀请函
2014/02/02 职场文书
财务科科长岗位职责
2014/03/10 职场文书
创建无烟单位实施方案
2014/03/29 职场文书
建筑公司员工自我鉴定
2014/04/08 职场文书
协议书的格式
2014/04/23 职场文书
《李广射虎》教学反思
2014/04/27 职场文书
和领导吃饭祝酒词
2015/08/11 职场文书
SQL 聚合、分组和排序
2021/11/11 MySQL