JavaScript字符串replaceAll方法实现

版权声明:本文为博主原创,转载加个原文章链接。 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);
}

猜你喜欢

转载自blog.csdn.net/xiaolongbaobushibao/article/details/81541999
今日推荐