iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >一次JavaScript正则的诡异经历记录
  • 709
分享到

一次JavaScript正则的诡异经历记录

2024-04-02 19:04:59 709人浏览 薄情痞子
摘要

目录背景问题原因总结事情是这样的,最近在写一个node功能的时候,遇到了一个正则的问题,觉得挺有意思的,就记录一下经历和最终问题原因,希望也能帮助到同样遇到的同学。 背景 我有一个N

事情是这样的,最近在写一个node功能的时候,遇到了一个正则的问题,觉得挺有意思的,就记录一下经历和最终问题原因,希望也能帮助到同样遇到的同学。

背景

我有一个Node服务,希望对访问进来的请求进行标记,如果请求进来的path是我定义的路由,那么将标记一个REQ,否则标记一个IVL,用于对于整个服务的日志记录进行输出。那么我通过服务启动时,根据定义的路由,生成一个RouterMap,通过访问进入时,判断path是否命中RouterMap来判断是否预期访问。

大概的代码如下:

export function getSourceMak(
  routerMap: AppRouterMap[],
  req: Http.IncomingMessage,
): SourceMark.REQ | SourceMark.IVL | SourceMark.TST {
  const { url, method, headers } = req;
  const pathname = url.split('?')[0];
  const userAgent = headers['user-agent'];
  // 安全扫描
  if (userAgent?.includes('TST(Tencent') && userAgent.includes('Team)')) {
    return SourceMark.TST;
  }
  for (const item of routerMap) {
    const { reg } = item;
    if (reg.test(pathname) && item.method === method.toLocaleLowerCase()) {
      return SourceMark.REQ;
    }
  }
  return SourceMark.IVL;
} 

因为涉及到一些动态路由的原因,不能直接通过path进行相等判断,需要对相应的路由规则生成一个对应的正则表达式,并且在服务启动时生成,保存在内存中进行复用。

生成正常代码如下:

export function createRouterRegexp(url) {
  const urlBlock = url.split('/');
  const regBlock = urlBlock.map((block) => {
    if (block[0] === ':') {
      return '((?!/).)*';
    }
    return block;
  });
  return new RegExp(`^${regBlock.join('/')}$`, 'ig');
}

问题

然后在进行调试的时候发现一个奇怪的现象,假设我有一个路由为GET /cats/find的路由,通过打点发现对应的正则表达式,/^\/cats\/find$/gi对/cats/find进行匹配的时候,第一次为true,第二次为false,第三次为true,第四次为false,以此类推。

经过反复验证,node代码并没有存在问题,正则表达式也没有问题,那么我在浏览器中尝试复现一下,也是得出同样的问题。至此我很确定,一定是有一些正则相关的坑是我以前没有注意到。于是我反查了一下javascript的文档,终于被我找到原因。

原因

通过查找MDN正则相关的文档,被查到以下说明

"nolink">当设置全局标志的正则使用test()

如果正则表达式设置了全局标志,test() 的执行会改变正则表达式 lastIndex属性。连续的执行test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,(exec() 同样改变正则本身的 lastIndex属性值).

下面的实例表现了这种行为:

var regex = /foo/g; 
// regex.lastIndex is at 0 
regex.test('foo'); // true 
// regex.lastIndex is now at 3 
regex.test('foo'); // false

RegExp.prototype.test() - JavaScript | MDN

这不就是我遇到的问题吗?

通过文档说明得知,当我们正则表达式带有g标识进行全局匹配时,匹配成功后,regex实例中会有一个lastIndex属性去记录本次命中正则的最后一位的下标+1,用于在下一次调用test的时候,从lastIndex开始进行匹配。 以前我没有遇到过大概率是因为以下原因:

每次进行正则校验时,都重新生成正则实例:/^\/cats\/find$/gi.test('/cats/find') 。

但是因为这次我将正则实例保存,并反复使用。从而导致问题。

并且通过验证得出,当匹配成功后,lastIndex会记录下一次开始的位置,但是当匹配失败,lastIndex会归零从头开始。

至此这一次被坑经历耗时60分钟左右,耽误了吃饭最佳时间,导致饭堂菜都快没有。但是同时也收获到JavaScript在正则上一个容易被忽略的坑。好像也不亏。

总结

到此这篇关于一次JavaScript正则的诡异经历记录的文章就介绍到这了,更多相关JavaScript正则经历内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 一次JavaScript正则的诡异经历记录

本文链接: https://www.lsjlt.com/news/146728.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一次JavaScript正则的诡异经历记录
    目录背景问题原因总结事情是这样的,最近在写一个Node功能的时候,遇到了一个正则的问题,觉得挺有意思的,就记录一下经历和最终问题原因,希望也能帮助到同样遇到的同学。 背景 我有一个N...
    99+
    2024-04-02
  • 记一次真实的网站被黑经历
    【本文转自爪哇笔记  作者:小柒2012 原文链接:http://tech.it168.com/a2018/0629/3212/000003212205.shtml】前言距离上次被DDOS攻击已经有10天左右的时间,距离上上次已经...
    99+
    2023-06-04
  • 记录nacos一次踩坑经历,报错 403 authorization failed! unknown user
    记录nacos一次踩坑经历,报错 403 authorization failed! 权限未开启正常读取 本人在学习springcloud alibaba时配置nacos的时候,如果未开启权限认证是正常的 nacos server中的配置:...
    99+
    2023-08-23
    java spring boot spring cloud
  • 一次java异步任务的实战记录
    目录前言一、什么是异步任务二、SpringBoot + Async三、踩坑日记四、解决五、总结前言 最近在开发中遇到一个埋点的需求,考虑到不能影响原有业务逻辑,于是准备写一个异步任务...
    99+
    2024-04-02
  • 一个关于JS正则匹配的踩坑记录
    最近发现在JS里的正则匹配有一个坑,而且当时很莫名奇妙,一度让我怀疑出现了灵异事件。 下面是踩坑代码 var str=["二七1","二七2","金水","二七3","二七...
    99+
    2024-04-02
  • javascript中使用正则test( )第一次是true,第二次是false的示例分析
    小编给大家分享一下javascript中使用正则test( )第一次是true,第二次是false的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下...
    99+
    2024-04-02
  • 一次.net core异步线程设置超时时间的实战记录
    目录前言:需求背景:需求提炼:.net里设置超时的 Task测试代码测试截图搞定收工总结前言: 刷帖子看到一篇 Go 记录一次groutine通信与context控制 看了一下需求背...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作