前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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数据处理

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

前瞻 (?=...) 检查当前位置右边是什么,后顾 (?<=...) 检查左边是什么。它们只做判断、不吃字符,被检查的内容不会出现在匹配结果里。前面加 ! 就变成「不能是」:(?!...) 和 (?<!...)。

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

只检查、不消费的四种断言

  1. (?=x) 与 (?!x)正向和负向前瞻,要求右边是或不是 x
  2. (?<=x) 与 (?<!x)正向和负向后顾,要求左边是或不是 x
  3. 零宽断言成功后读取位置不动,后面的表达式从原地继续匹配

断言检查的是一个位置,不是一段字符。把前瞻写在要匹配内容的左边,往往会让整条正则永远匹配不上。

核心回答

先记住这个答案

前瞻和后顾都叫环视断言,作用是在某个位置检查上下文,但不把上下文算进匹配结果。前瞻 (?=...) 检查右边,后顾 (?<=...) 检查左边;把 = 换成 ! 就是反过来的「不能是」。比如 /(?<=\$)\d+/ 匹配美元符号后面的数字,结果里只有数字,没有 $。它们最常见的用途是提取「某个前缀后面的内容」和「在满足条件的位置插入字符」。

  • 前瞻看右边,后顾看左边,都不进 match[0]
  • = 表示必须是,! 表示不能是
  • 多个前瞻叠在开头,等于多个条件同时成立
  • 后顾写在要匹配内容的左边,前瞻写在右边

用前瞻写千分位格式化

面试最常出现的前瞻题就是给数字加千分位逗号。这里用到的不是「匹配数字」,而是「找到应该插逗号的位置」。

一行正则找出所有插逗号的位置JavaScript
const format = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ',')

console.log(format(1234567)) // 1,234,567
console.log(format(1000))    // 1,000
console.log(format(999))     // 999,不需要逗号
查看输出与解释
1,234,567
1,000
999

这条正则没有消费任何数字,每次匹配到的都是一个空位置,replace 就往这个位置塞一个逗号。拆开看:\B 要求这里不是单词边界,排除了数字最左边的位置,避免出现 ,123。(?=(\d{3})+(?!\d)) 要求右边是 3 的整数倍个数字,而且这串数字之后不能再有数字,也就是一直数到末尾。 比如在 1234567 里,1 和 2 之间的位置右边是 234567,正好 6 个数字,满足条件。2 和 3 之间右边是 34567,5 个,不满足。所以逗号只插在 1 后面和 4 后面。 前瞻不吃字符的好处在这里体现出来了:检查完右边之后,读取位置还在原地,下一个位置可以继续检查同一串数字。

用后顾提取前缀后面的内容

后顾解决的是另一类需求:我要的内容左边必须是某个东西,但我不想要这个东西。以前没有后顾,只能把前缀一起匹配出来再用捕获组取值。

取出美元金额,和不带美元符号的数字JavaScript
const text = '原价 $120,折后 $99,运费 15 元'

// 左边必须是 $
console.log(text.match(/(?<=\$)\d+/g).join(','))
// 左边不能是 $,\b 保证从数字开头算起
console.log(text.match(/(?<!\$)\b\d+/g).join(','))
查看输出与解释
120,99
15

第一条正则在每个数字前检查左边是不是 $,是就开始匹配。结果里没有 $,不用再手动 slice。 第二条用了负向后顾。只写 (?<!\$)\d+ 会出问题:120 的 1 前面是 $ 被排除了,但引擎会接着从 2 开始试,2 前面是 1 不是 $,于是匹配出 20。加上 \b 要求从数字的开头算起,才能只拿到 15。负向断言经常需要这样补一个边界。 JavaScript 的后顾还有个比很多语言宽松的地方:里面可以写不定长的内容,比如 (?<=\$\s*)。Python 标准库的 re 模块就要求后顾里的内容长度固定。

多个前瞻叠在一起就是「同时满足」
密码规则「至少 8 位,包含数字和小写字母」可以写成 /^(?=.*\d)(?=.*[a-z]).{8,}$/。两个前瞻都站在开头这个位置检查,都不移动读取位置,所以相当于在同一个起点连续检查两个条件,最后再由 .{8,} 真正匹配整串。不过实际项目里更推荐拆成几条独立规则,这样能告诉用户具体是哪一条没满足。
回答前,多想一步

容易答错的地方

把前瞻写在要匹配内容的左边
想匹配 $ 后面的数字,写成 /(?=\$)\d+/ 是不行的。前瞻要求当前位置右边是 $,紧接着 \d+ 又要求同一个位置右边是数字,一个字符不可能既是 $ 又是数字,所以永远匹配不上。检查左边要用后顾,前瞻只能放在要匹配内容的右边。
以为断言的内容会出现在结果里
断言只检查不消费,match[0] 里只有断言之外那部分表达式匹配到的字符。但断言里如果写了捕获组,比如 (?=(\d{3})+),捕获组的内容还是会出现在 match[1] 里。不需要读的时候写成 (?:...)。
试着用自己的话回答

面试官还会怎么问?

老浏览器不支持后顾,怎么降级?

后顾断言是 ES2018 加入的,Chrome 很早就支持,但 Safari 直到 16.4 才支持,更老的 iOS WebView 里写后顾会直接抛 SyntaxError,整个脚本都跑不起来。降级方法是把前缀放进匹配里,再用捕获组取值,比如 /\$(\d+)/g 配合 matchAll 取 m[1]。

负向前瞻 (?!...) 有什么典型用法?

排除某些情况。比如匹配不以 .min.js 结尾的 js 文件名,可以写 /^(?!.*\.min\.js$).*\.js$/:先在开头检查整串里不会出现以 .min.js 结尾的情况,再正常匹配 .js 结尾。

前瞻断言会影响性能吗?

断言本身开销不大,问题出在断言里写了 .* 这种会扫完整串的表达式,又放在会被反复尝试的位置。比如千分位那条正则,每个位置都要往右扫到末尾,对超长数字串就是 O(n²)。平时格式化金额没问题,处理大文本时要留意。

从一道题,走向一组知识

把知识连起来

数据处理

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

不支持后顾断言时,常用捕获组把前缀一起匹配再取组内容,命名组能让这种写法更好读。

数据处理

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

用正则校验日期格式只能保证长得像,还要配合日期对象判断是不是真实存在的日期。

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

参考资料

  • Assertions

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

本题目录
  1. 先记住这个答案
  2. 用前瞻写千分位格式化
  3. 用后顾提取前缀后面的内容
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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