js replace 高级用法及适用场景

前言

近日刷编程题过程中发现善用 replace 及正则在处理数据时能做到极大的优雅简洁,特此记录分享一下。

replace 基本用法

语法: replace(regexp, string || function)
这里先介绍一下 replace 第二个参数可以传入两种类型:
1、字符串
  传入字符串会将每次正则匹配到的结果替换为该字符串

let str = '我不是sb,你是sb吗?';
// 第二个参数传入字符串
str = str.replace(/sb/g, '**');
console.log(str); // 我不是**,你是**吗?

2、回调函数
  传入回调函数会将每次正则匹配到的结果替换为该函数的返回值

let str = '我不是sb,你是sb吗?';
str = str.replace(/sb/g, () => '**');
console.log(str); // 我不是**,你是**吗?

replace 高级用法

1、第二个参数传入字符串时,可以在使用 $1-$9 获取正则捕获组的值,例如

let str = '我喜欢你';
str = str.replace(/(我喜欢)(你)/, '$1打完游戏再打$2');
console.log(str); // 我喜欢打完游戏再打你

适用场景

用于搜索结果关键字高亮显示非常舒服:

let str = '你爱我,我爱你,蜜雪冰城甜蜜蜜';
let search = '蜜雪冰城';
str = str.replace(new RegExp(`(${search})`, 'g'), '<span style="color: red;">$1</span>');
console.log(str); // 你爱我,我爱你,<span style="color: red;">蜜雪冰城</span>甜蜜蜜

2、第二个参数传入回调函数时,除了上述基本用法外,会在该回调函数调用时传入参数,方便对数据进行处理

回调函数调用时第一个参数为当前匹配到的值,最后一个参数为当前匹配到的值的起始下标,若有使用正则捕获组,则将$1-$9传入第一个参数之后,最后一个参数仍然为当前匹配到的值的起始下标

适用场景

  • 模仿 Vue 数据绑定
let data = {
    name: '是明啊',
    hobby: ['打游戏', '编程'],
};
let str = '你好,我叫{{name}},我喜欢{{hobby.join("、")}}';
str = str.replace(/\{\{([\d\D]+?)\}\}/g, (v, k) => {
    with (data) {
        return eval(k);
    }
});
console.log(str); // 你好,我叫是明啊,我喜欢打游戏、编程
  • 英文首字母自动大写
let str = 'I like play computer games and programming';
str = str.replace(/\s\w/g, v => v.toUpperCase());
console.log(str); // I Like Play Computer Games And Programming
  • 解析 url 参数
let url = 'https://www.baidu.com?user=admin&password=123#haha';
const params = {};
url.replace(/\??(\w+)=(\w+)&?/g, function (a, k, v) {
    params[k] = v;
});
console.log(params); // { user: 'admin', password: '123' }
  • 颜色格式转换
function rgb2hex(sRGB) {
    if (!/^rgb\((\d{1,3},\s*){2}\d{1,3}\)$/.test(sRGB)) return '请输入正确的rgb颜色代码';
    let  color = '#';
    sRGB.replace(/\d+/g, n => color += ('0' + (+n).toString(16)).slice(-2));
    return color;
}
const color = rgb2hex('rgb(255, 100, 0)');
console.log(color); // #ff6400
  • css 样式转大驼峰
function cssStyle2DomStyle(sName) {
    return sName.replace(/-[a-z]/g, (v, i) => i===0?v.slice(-1):v.slice(-1).toUpperCase());
    // 这里就运用了形参最后一个参数:当前匹配到的值的起始下标,处理中划线前置问题
}
const style1 = cssStyle2DomStyle('border-radius');
const style2 = cssStyle2DomStyle('-webkit-border-image');
console.log(style1); // borderRadius
console.log(style2); // webkitBorderImage
  • 货币换算
let str = '一部手机2999人民币,一件衣服200人民币';
str = str.replace(/\d+人民币/g, v => `${(v.slice(0, -3) * 0.1537).toFixed(2)}美元`);
console.log(str); // 一部手机460.95美元,一件衣服30.74美元
let str = '一部手机2999人民币,一件衣服200人民币';
str = str.replace(/(\d+)(人民币)/g, (v, $1, $2) => `${($1 * 0.1537).toFixed(2)}美元(${$1}${$2})`);
console.log(str); // 一部手机460.95美元(2999人民币),一件衣服30.74美元(200人民币)
  • 时间显示处理
function formatDate(t, str) {
    var obj = {
        yyyy: t.getFullYear(),
        yy: ('' + t.getFullYear()).slice(-2),
        M: t.getMonth() + 1,
        MM: ('0' + (t.getMonth() + 1)).slice(-2),
        d: t.getDate(),
        dd: ('0' + t.getDate()).slice(-2),
        H: t.getHours(),
        HH: ('0' + t.getHours()).slice(-2),
        h: t.getHours() % 12,
        hh: ('0' + t.getHours() % 12).slice(-2),
        m: t.getMinutes(),
        mm: ('0' + t.getMinutes()).slice(-2),
        s: t.getSeconds(),
        ss: ('0' + t.getSeconds()).slice(-2),
        w: ['日', '一', '二', '三', '四', '五', '六'][t.getDay()]
    };
    const reg = /y{2,4}|m{1,2}|d{1,2}|h{1,2}|s{1,2}|w/ig;
    return str.replace(reg, k => obj[k]);
}
const date1 = formatDate(new Date(1627430400000), 'yyyy-MM-dd HH:mm:ss 星期w');
const date2 = formatDate(new Date(1627430400000), 'yy-M-d H:m:s 星期w');
console.log(date1); // 2021-07-28 08:00:00 星期三
console.log(date2); // 21-7-28 8:0:0 星期三
posted @ 2021-07-28 19:14  是明啊  阅读(599)  评论(0编辑  收藏  举报