JavaScript 自己写一个 replaceAll() 函数

时间: 2019-09-07阅读: 60标签: 函数

JavaScript 的  replace()  方法可以在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

但是,只输入字符串的话,仅替换第一个字符,当然也可以用正则表达式来进行全局替换:

// 查找所有 word 替换成 words
string.replace(/word/g,"words");

那么,问题来了,如果我用的是变量呢?百度到可以这么来:

// 随便来一条字符串
let str = "How old are you? Yes, I'm very old!"
let search = "old";
// 使用 new RegExp(pattern,modifiers) 创建正则表达式
let pattern = new RegExp(search, "g");
let str = text.value.replace(pattern, "young");
// 结果:How young are you? Yes, I'm very young!

但是,不用 new RegExp 自己写一个函数,要怎么实现呢(我果然是太闲了)?

首先,摒弃掉 replace() 函数,自己来替换。

替换的话,不就是从前往后找想要替换的文并且一个个换掉嘛。

思路是这样的,用 indexOf() 方法返回指定的字符串在字符串中首次出现的位置,并用 slice(start, end)  方法提取找过但没有匹配项的,匹配的文字和还没找的三个部分,将第一部分和替换文字放入数组中,还没找的部分中再次使用这种办法,直至字符串末尾,将数组连起来成为一条字符串就是我想要的结果啦。

这是仅一次替换,咦,这不就是 replace() 嘛:

// 用于存放文字的数组
let array = [];
let data;
// 查询的文字第一次出现的位置
let start = oldText.indexOf(searchValue);
// 没有找到匹配的字符串则返回 -1 
if (start !== -1) {
    // 查找的字符串结束的位置
    let end = start + searchValue.length;
    // 添加没有匹配项的字符,即从头到查询的文字第一次出现的位置
    array.push(oldText.slice(0, start));
    // 添加替换的文字来代替查询的文字
    array.push(replaceValue);
    // 剩下没有查询的文字
    let remaining = oldText.slice(end, oldText.length);
    // 这是结果
    data = array[0] + array[1] + remaining;
} else {
    // 没找到呀
    data = "No Found" + searchValue + "!";
}
let textNode = document.createTextNode(data);
span.appendChild(textNode);

接下来进行全局替换,使用 while 循环,判定条件就是 indexOf(searchValue) 是否能找到文字,返回 -1 就停止循环。

let array = [];
// 用于存放未查找的文字
let remaining = oldText;
let data;
let start = oldText.indexOf(searchValue);
while (start !== -1) {
    let end = start + searchValue.length;
    array.push(remaining.slice(0, start));
    array.push(replaceValue);
    remaining = remaining.slice(end, remaining.length);
    start = remaining.indexOf(searchValue);
}
14 // 这是结果
data = array.join("") + remaining;

接着,再进一步,实现使用正则表达式来进行全局替换,大致思路是先找到正则匹配项,放入一个数组,在循环遍历每一项,使用上面的方法进行全局替换。

要注意的是,替换的数组不能有重复项,否则有可能出现问题,比如我想把 old 替换成 older,如果有两个 old 在数组中,最后的结果就会变成 olderer 。

/**
 * 字符串的全局替换
 * @param oldText {string} 原始字符串
 * @param searchValue {string} 需要替换的字符串
 * @param replaceValue {string} 替换后的字符串
 * @returns {string} 返回结果
 */
function replaceAll(oldText, searchValue, replaceValue) {
    let result = oldText;
    // 检查是否是正则表达式
    // 如果是正则表达式,则获得匹配内容
    let search;
    if (searchValue) {
        // 首先去掉空格
        search = searchValue.match(/\S+/g)[0];
        // 匹配以 / 符号开头 以 /img 形式结尾的内容
        search = search.search(/^\/[\s\S]*?\/[img]$/g);
    } else {
        search = -1;
    }
    // 为了方便直接创建一个数组用来存放需要替换的值
    let searchArray = [];
    if (search !== -1) {
        let pattern = searchValue.slice(searchValue.indexOf("\/") + 1, searchValue.lastIndexOf("\/"));
        let modifiers = searchValue.slice(searchValue.lastIndexOf("\/") + 1, searchValue.length);
        // 防止正则写的有问题,或者只是写的像正则实际不是而导致的 nothing to repeat 报错。
        try {
            search = oldText.match(new RegExp(pattern, modifiers));
        } catch (e) {
            console.log(e);
            // 报错则默认为是需要替换的文本
            search = null;
            searchArray.push(searchValue);
        }
        if (search !== null) {
            // 匹配成功后去掉重复项
            search.forEach(function (item1) {
                // if(searchArray.includes(item1)){}
                // IE 不支持 array.includes() 所以自己写一个循环吧
                // 数组中有相同元素则为 true
                let alreadyIn = false;
                searchArray.forEach(function (item2) {
                    if (item1 === item2) {
                        alreadyIn = true;
                    }
                });
                if (!alreadyIn) {
                    searchArray.push(item1);
                }
            });
        } else {
            // 匹配失败也默认为是需要替换的文本
            searchArray.push(searchValue);
        }
    } else {
        // 不是正则表达式也需要添加进数组
        searchArray.push(searchValue);
    }
    // 来循环吧,把 search 里的每个元素换一遍,当然首先里面要有元素
    if (searchValue) {
        let remaining = result;
        searchArray.forEach(function (item) {
            // 将上一次替换结束的字符串赋值给未扫描的字符串变量
            remaining = result;
            let array = [];
            let start = remaining.indexOf(item);
            console.log(start);
            // 没有匹配项则返回源字符串
            if (start === -1) {
                result = remaining;
            }
            while (start !== -1) {
                let end = start + item.length;
                array.push(remaining.slice(0, start));
                array.push(replaceValue);
                remaining = remaining.slice(end, remaining.length);
                start = remaining.indexOf(item);
                result = array.join("") + remaining;
            }
        });
    }
    return result;
}


吐血推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入...

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入...

3.站长广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入...

4.休闲娱乐: 网页游戏入口... H5游戏入口... 绝地求生首次打折降价了点此访问

链接: http://www.fly63.com/article/detial/6311

Js map、reduce、filter 等高阶函数

高阶函数是对其他函数进行操作的函数,可以将它们作为参数或通过返回它们。简单来说,高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回。例如Array.prototype.map,Array.prototype.filter

a标签调用js函数写法总结

这是常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且javascript:协议作为a的href属性的时候不仅会导致不必要的触发window.onbeforeunload事件,在IE里面更会使gif动画图片停止播放。

JS中function

在js程序开始执行前,引擎会查找所有var声明的变量和function声明的函数,集中到当前作用域顶部集中创建,赋值留在原地;声明方式创建函数--会被声明提前

jQuery.toggleClass() 函数详解

toggleClass()函数用于切换当前jQuery对象所匹配的每一个元素上指定的css类名。所谓切换就是如果该元素上已存在指定的类名,则移除掉;如果不存在,则添加该类名。该方法检查每个元素中指定的类。

Js函数curry化

最近的某次面试被问到了两次相关的问题,但是自己居然都没答好,尤其第二次,先来看看面试官给的题目是什么样子的:这一问给我问懵逼了,add(1)(2)(3)() === add(0)(2)(4)();这样的咱会实现啊,你再多加几个参数咱也能实现啊

js中函数的原型

js中每一个构造函数都有一个prototype的属性,prototype指向一个对象,而这个对象的属性和方法都会被构造函数的实例所继承,因此,需要一些共享的属性和方法可以写在构造函数的原型中

JavaScript全局属性和全局函数

调用上面的全局函数而不是全局方法的属性是有意义的,因为函数是全局调用的,而不是任何对象。 无论如何,您也可以调用这些函数方法,因为它们是运行它们的全局对象的方法。在web浏览器中,全局对象是浏览器窗口

前端常用的js函数方法整理

判断js类型: js有自己判断方法 typeof 但是当他遇到引用类型的时候得到的结果往往不是我们想要的,有没有时候后台返回的参数是null或者undefined然后就被丢到了页面上,很难看,要每一个地方都去处理

用 await/async 正确链接Js中的多个函数

在我完成 electrade 的工作之余,还帮助一个朋友的团队完成了他们的项目。最近,我们希望为这个项目构建一个 Craiglist 风格的匿名电子邮件中继,其中包含 “serverless” Google Firebase Function

云函数

云函数提供了一种 直接在云上运行,无状态的、短暂的、由事件触发的代码 的能力。ServerLess,即无服务器架构,也叫轻服务,它包含两个部分,如下:

fly63.com版权所有,内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权,请与小编联系!情况属实本人将予以删除!

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全