JavaScript replace方法支持回调函数作参数,可动态获取匹配内容、分组、索引等信息;带g标志时每次匹配调用一次,否则仅首次匹配调用;参数顺序为:匹配字符串、各捕获组、起始索引、原字符串。

JavaScript 的 replace 方法支持用回调函数作为第二个参数,这比写死替换字符串灵活得多——它能动态获取匹配内容、分组、位置等信息,实现条件替换、计数、格式转换等高级操作。
回调函数的参数含义要记牢
当正则表达式带 g 标志时,回调会被每次匹配调用一次;不带 g 则只调用一次(仅首次匹配)。回调接收的参数顺序固定:
-
第一个参数:完整匹配的字符串(即
$&) -
后续参数:依次为各捕获组的匹配内容(对应
$1、$2…) - 倒数第二个参数:本次匹配在原字符串中的起始索引
- 最后一个参数:原始输入字符串
例如:'a1b2c3'.replace(/(\d)/g, (match, p1, offset, str) => `【${p1}】at ${offset}`) → "a【1】at 1b【2】at 3c【3】at 5"
用闭包实现带状态的替换
回调本身无状态,但可借助外层变量或闭包维持上下文,比如给匹配项编号、切换替换模板、统计次数:
立即学习“Java免费学习笔记(深入)”;
- 编号替换:
let i = 0; text.replace(/\b\w+\b/g, w => `[$i++].${w}`) - 奇偶交替:
let isOdd = true; str.replace(/\d+/g, n => isOdd ? `<em>${n}</em>` : `<strong>${n}</strong>`) - 避免重复处理:
const seen = new Set(); s.replace(/\w+/g, w => seen.has(w) ? w : (seen.add(w), `[new]${w}`))
安全提取并转换捕获组内容
正则中用括号定义捕获组后,回调参数就能精准拿到各部分。这对解析结构化文本特别有用:
- 日期格式转换:
'2023-04-05'.replace(/(\d{4})-(\d{2})-(\d{2})/, (_, y, m, d) => `${m}/${d}/${y}`) - HTML 属性转义:
html.replace(/]+)>/g, (_, tag) => ``) - 保留部分结构:
'url(https://a.com/img.png)'.replace(/url\(([^)]+)\)/, (_, _, url) => `url("${url.toLowerCase()}")`)
注意全局匹配与非全局匹配的区别
没有 g 标志时,即使正则能匹配多次,回调也只执行一次,且参数中捕获组数量仍按正则定义来——未匹配到的组值为 undefined。容易误判为“没生效”,其实是只处理了第一个匹配:
- 错误预期:
'a1 b2 c3'.replace(/(\d)/, (_, d) => `X${d}`)→"aX1 b2 c3"(只换第一个) - 正确做法:
'a1 b2 c3'.replace(/(\d)/g, (_, d) => `X${d}`)→"aX1 bX2 cX3" - 想确保全局:显式加
g;想只换一次:不加g,无需额外逻辑


















