字符串的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 相关文章推荐
Javascript中定义方法的另类写法(批量定义js对象的方法)
Feb 25 Javascript
javascript返回顶部效果(自写代码)
Jan 06 Javascript
Javascript代码在页面加载时的执行顺序介绍
May 03 Javascript
Javascript基础之数组的使用
May 13 Javascript
jquery 动态合并单元格的实现方法
Aug 26 Javascript
jQuery获取this当前对象子元素对象的方法
Nov 29 Javascript
JS实现页面进入和返回定位到具体位置
Dec 08 Javascript
10个最优秀的Node.js MVC框架
Aug 24 Javascript
AngularJS实现表单元素值绑定操作示例
Oct 11 Javascript
薪资那么高的Web前端必看书单
Oct 13 Javascript
React Native日期时间选择组件的示例代码
Apr 27 Javascript
Ajax异步刷新功能及简单案例
Nov 20 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
php foreach 参数强制类型转换的问题
2010/12/10 PHP
destoon利用Rewrite规则设置网站安全
2014/06/21 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
2014/06/23 PHP
JavaScript获得选中文本内容的方法
2008/12/02 Javascript
网页前台通过js非法字符过滤代码(骂人的话等等)
2010/05/26 Javascript
基于jquery的一行代码轻松实现拖动效果
2010/12/28 Javascript
可简单避免的三个JS发布错误的详细介绍
2013/08/02 Javascript
基于jQuery的JavaScript模版引擎JsRender使用指南
2014/12/29 Javascript
NodeJS学习笔记之Connect中间件模块(一)
2015/01/27 NodeJs
JS动态插入并立即执行回调函数的方法
2016/04/21 Javascript
Bootstrap导航条鼠标悬停下拉菜单
2017/01/04 Javascript
解决vue 引入子组件报错的问题
2018/09/06 Javascript
JavaScript实现的鼠标跟随特效示例【2则实例】
2018/12/22 Javascript
JavaScript面向对象编程小游戏---贪吃蛇代码实例
2019/05/15 Javascript
vue实现中部导航栏布局功能
2019/07/30 Javascript
vue props 单项数据流实例分享
2020/02/16 Javascript
[04:22]DOTA2大事件之护国神翼
2020/08/14 DOTA
python 排列组合之itertools
2013/03/20 Python
用Python中的字典来处理索引统计的方法
2015/05/05 Python
Ubuntu下Python2与Python3的共存问题
2018/10/31 Python
Flask核心机制之上下文源码剖析
2018/12/25 Python
python实现彩色图转换成灰度图
2019/01/15 Python
Python实现定制自动化业务流量报表周报功能【XlsxWriter模块】
2019/03/11 Python
windows上安装python3教程以及环境变量配置详解
2019/07/18 Python
基于python traceback实现异常的获取与处理
2019/12/13 Python
Django 返回json数据的实现示例
2020/03/05 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
python 实现汉诺塔游戏
2020/11/28 Python
小学毕业感言150字
2014/02/05 职场文书
2014年校长工作总结
2014/12/11 职场文书
公司禁烟通知
2015/04/23 职场文书
2016年元旦寄语
2015/08/17 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书
2016国培研修心得体会
2016/01/08 职场文书
python实现监听键盘
2021/04/26 Python
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis