正则判断图片格式_正则里面的 lastIndex

dff0d4d160a606a7f41a1a63cd94f117.png
好久没有写文章了,很惭愧。

昨天同事遇到了这样一个问题,用正则进行循环判断,简化的代码大概是下面这样:

var 

这里是不是有人会觉得奇怪,为什么第二个是 false 呢。

test()

其实如果我们仔细看过MDN上关于test的描述,应该就知道了:

eade6be0bc26471b2f63f93a2b730cca.png

关于这个lastIndex,很多小伙伴可能没有听过也没有用过,让我们看看下面的代码:

var 

可以看到,reg 含有一个不可枚举的 lastIndex 属性。当然,如果你直接用 Object.keys(reg) 是看不到的:

var 

(知识点:getOwnPropertyDescriptors() 和 keys() 的区别是什么呢。keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组。)

这个就是造成上面第二个是false的原因。因为每执行一次,其实我们的lastIndex都会变化:

var 

根据上面的代码可以看到,这个lastIndex是会循环的。

所以第二次就出了问题。如果我们想让一开始的代码正常工作,该怎么办呢?

var 

我们需要在每次执行后手动设置lastIndex。

test() 应用场景

我们举一个应用场景:后端传回来了一个图片 url 的数组,有 jpg、png 各种格式的,我们需要拿到以 jpg 结尾的图片:

首先,我们看看下面的代码:

const 

(关于判断图片格式的这个正则大家不要纠结,其实是不完善的,比如url的名字是 ajpg.jpg 这种也可以匹配到,这个不重要,不是本文重点)

乍一看,觉得没毛病。我们看看结果:

ade45c11f395f7b39cb57872f99e759d.png

WTF???

你肯定反应过来了,因为lastIndex变了,所以和预期不一致了,我们输出一下看看:

2a7f4eeee29880049eab6623223deb1d.png

可以看到,true和false是依次输出的,所以我们没有拿到全部的jpg格式的url。

还有,就是如果当前匹配失败了,lastIndex也会重置为0,这一点也很重要,不然后面的就匹配不到了。

所以解决方法之一就是手动重置lastIndex:

1386ffb89f65b6aa616fa93a21f5e210.png

其实,最好的方法就是直接去掉g,因为这种场景其实是不需要加上g的。这样lastIndex就一直是0,不会变了。结果也是符合预期的:

1c19cc50a586a4e08546bc777a7c7918.png

exec

此外,lastIndex 还和另一个正则方法 exec() 也是好兄弟,关系很近。用法和 test() 原理一样。

很多人分不清 exec 和 match 的关系,或者可能没有用过 exec。

`match` 和 `exec`的关系:

  • 首先,两个方法的来源是不一样的:
String
  • 然后,不加g的时候是一样的:

ab2a2efc7fc37e9bc3090469f02ad162.png
  • 然后,加了g的话:

match就没有捕获组了:

cd82654269421639c8d9fca88f955cf9.png

这个时候我们就需要用exec()方法了。

捕获组

关于捕获组,这里简单介绍一下。

捕获组分为四类:

  • 捕获 ()
  • 不捕获 (?:)
  • 正向捕获 (?=)
  • 反向捕获 (?!)

捕获组的功能很强大,这里就举两个例子:

例1:对日期进行任意格式的转换

var 

例2: 千分位数字

'12345678'

因此,exec结合捕获组就可以实现很多复杂的逻辑。

exec() 应用场景

举个例子,我们要把一个字符串` a1b2c3d4e5`里面的偶数的数字变成0。(方法肯定很多,这里只考虑用正则的方式)

肯定有同学说直接用 `replace` 就行了:

'a1b2c3d4e5'

(因为这里的转换条件比较简单,如果是很复杂的转换,比如我要把偶数的数字先转成ASCII码,然后反转呢?主要就是意思一下哈。)

b065b5e101c7dc0a67ea011a2a24c820.png

我个人觉得exec比match强大的地方在于它可以深入到内部,暂停执行,类似 generate 函数,而不像match一样是个黑盒。

exec() 和 lastIndex

关于这个,其实业务中感觉用的不多,就举个例子吧:

var 

代码大家肯定看得懂,我就不说了。`match` 是无法实现这样的功能的,因为匹配完就丢弃了。

使用exec() 要注意的点就是不要写出死循环(毕竟有while)。

(完)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
普通的JS正则表达式用来在字符串中匹配特定的模式。在JS中,我们可以使用正则表达式字面量或者RegExp构造函数来创建正则表达式。正则表达式有两个常用方法exec和test。 当正则是全局匹配时,每一次匹配完成后,都会修改lastIndex属性。例如,下面的代码展示了使用test方法来匹配字符串并查看lastIndex的变化: var regex = /a/g; console.log( regex.test("a"), regex.lastIndex ); // => true 1 console.log( regex.test("aba"), regex.lastIndex ); // => true 3 console.log( regex.test("ababc"), regex.lastIndex ); // => false 0 如果没有全局标志g,正则表达式会从字符串的第0个字符开始尝试匹配。例如,下面的代码展示了在没有全局标志g的情况下,使用test方法进行匹配时lastIndex的变化: var regex = /a/; console.log( regex.test("a"), regex.lastIndex ); // => true 0 console.log( regex.test("aba"), regex.lastIndex ); // => true 0 console.log( regex.test("ababc"), regex.lastIndex ); // => true 0 除了test方法,我们也可以使用exec方法来执行正则表达式的匹配。exec方法返回一个数组,数组的第一个元素是匹配到的字符串,后面的元素是捕获组的匹配结果。 有时候我们需要构建动态的正则表达式,这时可以使用RegExp构造函数。例如,下面的代码展示了使用RegExp构造函数来构建正则表达式: var className = "high"; var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); console.log( regex.source ) // => (^|\s)high(\s|$) 在正则表达式中,^表示匹配字符串的开始,$表示匹配字符串的结束。当我们想要整体匹配时,需要同时使用^和$。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [第七章 正则表达式编程](https://blog.csdn.net/qq_40241957/article/details/98767510)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值