前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库JavaScript 正则 命名捕获组 用法
JavaScript数据处理

正则的命名捕获组怎么用,和 match[1] 这种写法比好在哪?

普通捕获组按左括号的顺序编号,用 match[1]、$1 取;命名捕获组写成 (?<name>...),用 match.groups.name 取。正则里加减分组时,数字下标会整体错位,名字不会变,所以字段多的正则优先用命名组。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数据处理
先看核心答案读代码示例
理解线索

给捕获结果起名字

  1. (?<name>...)声明命名组,同时照常按顺序占一个数字下标
  2. groups匹配结果上的对象,键是组名,值是捕获到的字符串
  3. $<name> 与 \k<name>前者在替换字符串里引用,后者在正则内部反向引用

正则里一个命名组都没有时,m.groups 是 undefined,不是空对象,直接解构会报错。

核心回答

先记住这个答案

命名捕获组就是给分组起名字,写成 (?<name>...),匹配后通过结果上的 groups 对象按名字取值,比如 m.groups.year。它和普通的数字捕获组并不冲突,命名组照样按顺序占一个下标,m[1] 仍然能取到。好处主要在维护:正则里新增或删除一个分组,后面所有数字下标都会跟着错位,按名字取值则不受影响。替换字符串里用 $<name> 引用,正则内部反向引用用 \k<name>。

  • 写法 (?<year>\d{4}),读取 m.groups.year
  • 命名组照样占数字下标,m[1] 也能取到
  • 替换字符串用 $<name>,正则内部用 \k<name>
  • 可选分支没命中时,对应的值是 undefined

用日期解析看两种写法的区别

最典型的场景是从一段文本里拆出多个字段,比如从日志里取出年月日。

解构 groups 拿到每个字段JavaScript
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const m = re.exec('发布于 2026-09-29')

// 命名组可以直接解构,数字下标也照常可用
const { year, month, day } = m.groups
console.log(m[1], year, month, day, m.index)
查看输出与解释
2026 2026 09 29 4

m[1] 和 m.groups.year 拿到的是同一个值,命名只是多提供了一种按名字访问的方式。 这时候看不出命名组有多大优势。设想需求变了,日期前面可能带一个可选的时区前缀,正则前面要加一个分组 (UTC\+\d )?。用数字下标的代码,m[1] 就从年份变成了时区,后面的 m[2]、m[3] 全部错位,而且不会报错,只会悄悄取错值。用 groups 的代码一行都不用改。 正则越长、分组越多,这个差别越明显。解析 URL、日志、版本号这类有好几个字段的场景,命名组基本是标配。反过来,只有一个分组的短正则,用 m[1] 也完全没问题。

在 replace 里引用命名组

replace 有两种用法:第二个参数是字符串,或者是回调函数。两种用法都能按名字引用分组。

替换字符串和回调各写一次JavaScript
const s = '2026-09-29'
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/

// 替换字符串里用 $<name>
console.log(s.replace(re, '$<day>/$<month>/$<year>'))

// 回调里:有命名组时,最后一个参数就是 groups 对象
const out = s.replace(re, (...args) => {
  const g = args[args.length - 1]
  return `${g.year}年${Number(g.month)}月`
})
console.log(out)
查看输出与解释
29/09/2026
2026年9月

替换字符串里的语法是 $<name>,和 $1 同一套规则,引擎在替换时识别。回调函数的参数依次是完整匹配、每个捕获组、匹配位置、原字符串,正则里有命名组时,最后还会多一个 groups 对象。因为前面参数的个数取决于分组数量,所以直接取最后一个参数最稳,不用去数位置。

正则内部的反向引用 \k<name>
反向引用的意思是「这里要出现和前面某个组一模一样的内容」。数字写法是 \1,命名写法是 \k<name>。比如 /(?<word>\w+) \k<word>/ 能找出 go go 这种重复的单词,对 go to 则匹配失败。检查 HTML 开闭标签是否成对、引号是否前后一致,都会用到这种写法。
回答前,多想一步

容易答错的地方

在替换字符串里写 ${name}
${name} 是模板字符串的语法,放在普通单引号字符串里就是字面文本,'go'.replace(/(?<w>o)/, '${w}') 得到的是 g${w}。如果写在反引号模板字符串里,它会在调用 replace 之前就去读一个叫 name 的变量,和捕获组无关。正确写法是 $<name>。
以为没命中的命名组不会出现在 groups 里
/(?<num>\d+)|(?<word>[a-z]+)/ 去匹配 abc,只有 word 分支命中,但 groups 里 num 这个键仍然存在,值是 undefined。用 JSON.stringify 打印时 undefined 会被省略,看起来像是没有这个键,其实 'num' in m.groups 是 true。所以读可选分支的组时要先判空,别直接调字符串方法。
试着用自己的话回答

面试官还会怎么问?

正则里没写命名组时,groups 是什么?

是 undefined。所以写通用工具函数时,const { a } = m.groups 要改成 const { a } = m.groups ?? {},否则正则里没有命名组就会抛 TypeError。有命名组时,groups 是一个没有原型的对象,只包含组名,不会有 toString 这类继承来的属性。

同一个名字能用两次吗?

在同一个分支里重复命名会直接报 SyntaxError,正则都创建不出来。组名也要符合标识符规则,不能以数字开头,不能带连字符,比如 (?<first-name>...) 是非法的,要写成 firstName。

只想分组、不想捕获怎么写?

写成非捕获组 (?:...)。比如 (?:https?|ftp):\/\/ 里的括号只是为了让 | 的作用范围限定在协议上,不需要读取它。多余的捕获组不仅占下标、让后面的编号更难数,也会让结果对象里多出无用的值。

从一道题,走向一组知识

把知识连起来

数据处理

正则里的前瞻和后顾断言怎么用,有什么区别?

取前缀后面的内容有两种写法,一种是命名组把前缀一起匹配,另一种是用后顾断言把前缀排除在结果外。

数据处理

new Date 解析失败了怎么判断?instanceof Date 为什么不够?

命名组只能把日期字符串拆成年月日,拆出来的值是不是合法日期,还要用日期对象再校验一次。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Groups and backreferences

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 用日期解析看两种写法的区别
  3. 在 replace 里引用命名组
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑