前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 正则 sticky标志y与global标志g区别
JavaScript数据处理

正则的 y 标志和 g 标志有什么区别,y 适合用在哪?

g 和 y 都从 lastIndex 开始匹配,区别在于找不到时怎么办。g 会继续往后找,y 只认 lastIndex 这一个位置,对不上就直接失败。所以 y 适合写词法分析器:一个 token 接一个 token 地读,中间不允许有认不出的字符被悄悄跳过。

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

往后找还是原地试

  1. g 全局从 lastIndex 开始向右搜索,能跳过不匹配的字符
  2. y 粘连匹配必须从 lastIndex 开始,差一个字符都算失败
  3. lastIndex两种标志共用的读取位置,成功后挪到匹配末尾

y 不会自动跳过空格。词法分析时要把空白也写进规则里,或者单独用一条规则把它吃掉。

核心回答

先记住这个答案

g 和 y 都让正则对象带上状态,exec 和 test 都从 lastIndex 开始匹配,成功后把 lastIndex 挪到匹配末尾,失败后归零。区别只有一个:g 在当前位置匹配不上时会继续往右找,y 不会,它要求匹配必须正好从 lastIndex 开始。y 是 sticky 的缩写,意思是「粘在这个位置上」。它最典型的用途是写词法分析器,一段一段连续地读取输入,遇到认不出的字符能立刻知道出错位置,而不是跳过去。

  • g 从 lastIndex 往后搜,y 只在 lastIndex 处试
  • 两者成功都挪 lastIndex,失败都归零
  • y 的典型用途是逐个读取 token 的词法分析
  • ^ 只认整串开头,和 y 不是一回事

同一个起点,g 和 y 的不同反应

先把两个正则的 lastIndex 都设成 1,而目标字符在下标 2,看看它们怎么处理。

从下标 1 开始找 aJavaScript
const text = 'x a'
const global = /a/g
const sticky = /a/y

global.lastIndex = 1
sticky.lastIndex = 1

console.log(global.exec(text)?.index, global.lastIndex) // 往后找到下标 2
console.log(sticky.exec(text), sticky.lastIndex)        // 下标 1 是空格,直接失败

sticky.lastIndex = 2
console.log(sticky.exec(text)?.index, sticky.lastIndex) // 起点对准了才成功
查看输出与解释
2 3
null 0
2 3

g 从下标 1 开始,发现是空格,于是往右移一位,在下标 2 找到了 a。y 在下标 1 就要求必须是 a,是空格就失败,lastIndex 归零。把起点改到 2 之后 y 才成功。 可以这样类比:g 像在一本书里从书签处往后翻着找某个词,y 像逐字朗读,读到的这个字必须是预期的那个,不是就停下报错。

y 的真正用途:写词法分析器

词法分析就是把一串字符切成一个个有意义的单元,比如把 12 + 3*4 切成 12、+、3、*、4。它最重要的要求是不能漏:每个字符都必须被某条规则认领,认不出来就要报错。用 g 做不到这一点,因为它会悄悄跳过认不出的字符。

一个四则运算的 tokenizerJavaScript
const token = /\s*(\d+|[+\-*\/])/y // 先吃掉空白,再读一个数字或运算符

function tokenize(src) {
  const out = []
  token.lastIndex = 0 // 每次新输入先归零
  while (token.lastIndex < src.length) {
    const start = token.lastIndex
    const m = token.exec(src)
    if (!m) throw new SyntaxError(`第 ${start} 位无法识别`)
    out.push(m[1])
  }
  return out
}

console.log(tokenize('12 + 3*4').join(' '))
try { tokenize('1 + x') } catch (e) { console.log(e.message) }
查看输出与解释
12 + 3 * 4
第 3 位无法识别

每次 exec 成功,lastIndex 正好停在这个 token 的末尾,下一轮就从这里接着读,不需要手动截字符串。读到 1 + x 的下标 3 时,\s* 吃掉空格后遇到 x,数字和运算符都对不上,exec 返回 null,我们立刻知道出错位置在哪。 如果把这里的 y 换成 g,输入 1 + x 2 就不会报错了:exec 遇到 x 对不上,会继续往右找,直接读到后面的 2,最后得到 1 + 2。非法字符被悄悄吞掉,这正是词法分析最不能接受的。 以前没有 y 时,常见做法是每读一个 token 就 src.slice(pos) 截出剩余部分,再用 ^ 开头的正则去匹配。这样还得自己维护 pos,每轮都多一次截取。y 直接在原字符串上用 lastIndex 定位,读取位置由正则自己推进,代码更短也更不容易算错偏移。

回答前,多想一步

容易答错的地方

以为 y 和 ^ 是一回事
^ 永远只匹配整个字符串的开头(开了 m 标志时是每行开头),不管 lastIndex 是多少。/^a/y 把 lastIndex 设成 2 去测 'baa',结果是 false,因为下标 2 不是字符串开头。y 的锚点是可以移动的 lastIndex,所以才能一段段往后读。
以为 y 会自动跳过空白
y 只在 lastIndex 处原地尝试。上面的 tokenizer 里规则开头写了 \s*,就是为了把空白也吃掉。如果去掉它,12 + 3 读完 12 之后下标 2 是空格,直接失败。另外要当心能匹配空字符串的规则,它成功了却不推进 lastIndex,循环会原地打转。
试着用自己的话回答

面试官还会怎么问?

g 和 y 能一起用吗?

可以,而且在 match、replace 里有明确的效果:只拿从头开始连续挨着的那些匹配,中间一断就停。'aaba'.match(/a/g) 找到 3 个 a,'aaba'.match(/a/gy) 只找到前 2 个,因为下标 2 的 b 把连续性打断了。'aaba'.replace(/a/gy, '-') 的结果是 --ba。

怎么判断一个正则有没有 y 标志?

读 re.sticky 属性,返回布尔值。也可以看 re.flags,它会按固定顺序列出所有标志,比如 /a/yg 的 flags 是 gy。

为什么 matchAll 不太适合做词法分析?

matchAll 必须带 g,即使同时带 y,它也只会在匹配断开时静默结束,你拿不到「在第几位断开」这个信息,也没法在中途根据上一个 token 切换规则。词法分析需要在每一步检查失败位置、有时还要换一条规则去试,用 exec 加 lastIndex 手动控制更合适。

从一道题,走向一组知识

把知识连起来

数据处理

正则的贪婪匹配和非贪婪匹配有什么区别?

写 token 规则时量词是贪婪还是懒惰,决定了 y 每一步读进来的 token 有多长。

数据处理

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

词法规则里常用前瞻判断 token 的结尾,比如关键字后面不能紧跟字母,否则就是标识符的一部分。

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

参考资料

  • RegExp.prototype.sticky

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

本题目录
  1. 先记住这个答案
  2. 同一个起点,g 和 y 的不同反应
  3. y 的真正用途:写词法分析器
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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