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 星期三