字符串的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 相关文章推荐
DOM基础教程之事件对象
Jan 20 Javascript
JavaScript判断字符长度、数字、Email、电话等常用判断函数分享
Apr 01 Javascript
基于jquery实现三级下拉菜单
May 10 Javascript
VC调用javascript的几种方法(推荐)
Aug 09 Javascript
JavaScript中数组Array方法详解
Feb 27 Javascript
Javascript前端经典的面试题及答案
Mar 14 Javascript
vue实现长图垂直居上 vue实现短图垂直居中
Oct 18 Javascript
微信小程序中换行空格(多个空格)写法详解
Jul 10 Javascript
Layui表格行工具事件与数据回填方法
Sep 13 Javascript
layui使用templet格式化表格数据的方法
Sep 16 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
Sep 22 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 27 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
哪吒敖丙传:新人物二哥敖乙出场 小敖丙奶气十足
2020/03/08 国漫
php对关联数组循环遍历的实现方法
2015/03/13 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
利用php + Laravel如何实现部署自动化详解
2017/10/11 PHP
PHP获取数据库表中的数据插入新的表再原删除数据方法
2018/10/12 PHP
PHP+swoole+linux实现系统监控和性能优化操作示例
2019/04/15 PHP
Prototype 工具函数 学习
2009/07/23 Javascript
基于jquery的分页控件(C#)
2011/01/06 Javascript
Jquery中给animation加更多的运作效果实例
2013/09/05 Javascript
jQuery 如何先创建、再修改、后添加DOM元素
2014/05/20 Javascript
jQuery中not()方法用法实例
2015/01/06 Javascript
jQuery计算文本框字数及限制文本框字数的方法
2016/03/01 Javascript
50 个 jQuery 插件可将你的网站带到另外一个高度
2016/04/26 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析
2017/04/13 Javascript
了解在JavaScript中将值转换为字符串的5种方法
2019/06/06 Javascript
js实现无限瀑布流实例方法
2019/09/16 Javascript
使用Layer组件弹出多个对话框(非嵌套)与关闭及刷新的例子
2019/09/25 Javascript
js实现的订阅发布者模式简单示例
2020/03/14 Javascript
在vue-cli3.0 中使用预处理器 (Sass/Less/Stylus) 配置全局变量操作
2020/08/10 Javascript
Python求导数的方法
2015/05/09 Python
python+Django+apache的配置方法详解
2016/06/01 Python
Python绑定方法与非绑定方法详解
2017/08/18 Python
django项目搭建与Session使用详解
2018/10/10 Python
selenium使用chrome浏览器测试(附chromedriver与chrome的对应关系表)
2018/11/29 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
python提取log文件内容并画出图表
2019/07/08 Python
python装饰器相当于函数的调用方式
2019/12/27 Python
Django Admin后台模型列表页面如何添加自定义操作按钮
2020/11/11 Python
python爬虫利用代理池更换IP的方法步骤
2021/02/21 Python
超酷炫 CSS3垂直手风琴菜单
2016/06/28 HTML / CSS
总结html5自定义属性有哪些
2020/04/01 HTML / CSS
FLIR美国官网:热成像, 夜视和红外摄像系统
2018/07/13 全球购物
慕尼黑山地运动、户外服装和体育用品专家:Sporthaus Schuster
2019/08/27 全球购物
建筑专业毕业生求职信
2014/09/30 职场文书
公司安全管理制度范本
2015/08/05 职场文书