Appearance
09. 连续两次正则测试结果不一样
解释
执行下面的代码,会出乎意料,两次 test
正则匹配的结果不一样。
js
const r = /foo/g
let s = 'foobar'
r.test(s) // true
r.test(s) // false
1
2
3
4
2
3
4
这是因为当给正则式加了 g
标志后,test
方法会修改正则对象的 lastIndex
属性的值。初始状态下 lastIndex
为 0
,每次执行 test
后,lastIndex
会被设置为上一次匹配结果的末尾位置的索引,直到字符串末尾,又变为 0
。每次正则匹配都从 lastIndex
处开始匹配。
js
const re = /foo/g
let str = 'foo-foo-foo'
re.lastIndex // 0
re.test(str) // true
re.lastIndex // 3
re.test(str) // true
re.lastIndex // 7
re.test(str) // true
re.lastIndex // 11
re.test(str) // false
re.lastIndex // 0
re.test(str) // true
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
解决
解释了这种现象之后,解决方法如下:
- 需要用到连续匹配的情况,例如循环里匹配,每次重置正则属性
lastIndex=0
- 去掉
g
标志,在非全局匹配模式下,lastIndex
的值始终为0
。
总结
- 所有的正则表达式都有一个
lastIndex
属性,用于记录上一次匹配结束的位置。如果不是全局匹配模式,那lastIndex
的值始终为0
,在匹配过一次后,将会停止匹配。 - 全局模式下,
test
和exec
方法都会修改lastIndex
的值。