版权声明:本文为博主原创,转载加个原文章链接。 https://blog.csdn.net/xiaolongbaobushibao/article/details/81541999
JavaScript字符串replaceAll方法实现
前言
有时候需要使用替换字符串某些内容,我们会想到:String.prototype.replace
//想把所有A替换成空字符串
"ABCDABCD".replace("A","");//输出 BCDABCD,只是替换了第一个A
所以我们可以使用正则:
"ABCDABCD".replace(/A/g,"");//输出BCDBCD 满足需求了
能不能抽成一个方法或者成为原型链的方法呢?
String.prototype.replaceAll = function (substr, replacement){
var reg = new RegExp(substr,"g");
return "ABCDABCD".replace(reg,replacement);
}
"ABCDABCD".replaceAll("A","");//输出BCDBCD 满足需求了
但是但是!当替换的词是正则的关键词呢,如*?
"*BCD*BCD".replaceAll("*","");
//报错:
/*
VM2751:2 Uncaught SyntaxError: Invalid regular expression: /* /: Nothing to repeat
at new RegExp (<anonymous>)
at String.replaceAll (<anonymous>:2:15)
at <anonymous>:1:12
*/
问题来了,如何规避这个问题呢?
一、循环替换
- 实现
String.prototype.replaceAll = function (substr, replacement) {
var placehoder = "bcfc28c6c5e06d4a9ac99817471f2b78";
// 占位字符 为什么使用placehoder占位? var string = "AABB"; string.replace("AB","") == ""
var string = this;
while (string.indexOf(substr) != -1) {
string = string.replace(substr, placehoder);
}
while (string.indexOf(placehoder) != -1) {
string = string.replace(placehoder, replacement);
}
return string
}
"ABCDCCCCE".replace("C","");// ABDE
- 原理
- 使用一个uuid去替换当前字符串内需要替换的字符,算是占位
- 把新生成的有占位字符的字符串替换其为目标字符
- 又生成一个新的字符串
- 为什么使用placehoder占位?
var string = "AABB";
var substr = "AB";
while (string.indexOf(string) != -1) {
string = string.replace(substr, "");//循环第一次:string == "AB",本来替换一次就可以了,没想到替换之后还能继续替换,于是进入下个替换循环
}
//最终结果:""
二、正则替换
2.1 正则一
- 实现
String.prototype.replaceAll = function (substr, replacement) {
var getRegExp = function (sub, mod) {
if (typeof sub !== 'string') {
return new RegExp(sub);
}
//转义需要转义的正则关键字如 $需要转义成\$
var regExpStr = sub.replace(/\$|\(|\)|\*|\+|\.|\[|\]|\?|\\|\^|\{|\}|\|/g, function () {
return "\\" + arguments[0];
})
return new RegExp(regExpStr, mod);
}
var reg = substr instanceof RegExp ? substr : getRegExp(substr, "g");
return this.replace(reg, replacement)
}
"ABCDCCCCE".replace("C","");// ABDE
- 原理
直接实例化正则对象,对于关键字支持不好.
var substr = "*";
var reg = new RegExp(substr,"g"); //报错
var substr = "\\*";
var reg = new RegExp(substr,"g");//可以使用,但是使用者需要输入\\*,对使用者不方便
加入一个生成正则对象的方法:
var getRegExp = function (sub, mod) {}//转义需要转义的正则关键字如 $需要转义成\$
2.2 正则二
直接实例化正则对象,对于关键字支持不好,所以我们将字符串转成Unicode
:
var encodeUnicode = function (str) {
var res = [];
for ( var i=0; i<str.length; i++ ) {
res[i] = ( "00" + str.charCodeAt(i).toString(16) ).slice(-4);
}
return "\\u" + res.join("\\u");
}
var getRegExp = function (substr,modifiers) {
if(typeof str !== 'string'){
return new RegExp(str);
}
return new RegExp(encodeUnicode(substr),"u"+(modifiers||""));
}
String.prototype.replaceAll = function (substr, replacement) {
var reg = substr instanceof RegExp ? substr : getRegExp(substr, "g");
return this.replace(reg, replacement)
}
三、切割数组再组装数组
- 实现
String.prototype.replaceAll = function (substr, replacement) {
return this.split(substr).join(replacement);
}
"ABCDCCCCE".replace("C","");// ABDE
- 原理
这个是最好理解的,把字符串以关键词分割为数组,然后将数组拼接。需要比较熟悉字符和数组的原型方法。
总结
三种方法有好有坏,功能算是实现了。不过追加方法到原型上不是个好的做法,因为你不知道哪一年ES会不会退出官方的标准实现replaceAll,到时候冲突了就不好了。所以建议做法是:
function replaceAll(targetString,substr, replacement){
return ....
}
//比如
function replaceAll(targetString,substr, replacement){
return targetString.split(substr).join(replacement);
}