JavaScript RegExp 对象的lastIndex 属性
说明
该属性存放一个整数,它声明的是上一次匹配文本之后的第一个字符的位置。
上次匹配的结果是由方法 RegExp.exec() 和 RegExp.test() 找到的,它们都以 lastIndex 属性所指的位置作为下次检索的起始点。这样,就可以通过反复调用这两个方法来遍历一个字符串中的所有匹配文本。
该属性是可读可写的。只要目标字符串的下一次搜索开始,就可以对它进行设置。当方法 exec() 或 test() 再也找不到可以匹配的文本时,它们会自动把 lastIndex 属性重置为 0。
提示和注释
重要事项:不具有标志 g 和不表示全局模式的 RegExp 对象不能使用 lastIndex 属性。
提示:如果在成功地匹配了某个字符串之后就开始检索另一个新的字符串,需要手动地把这个属性设置为 0。
例子
/aaa/g.test('aaa')
//结果为true
const ARE = /aaa/g
const testArr = ['aaa','aaa','aaa']
for(let i = 0; i < testArr.length; i++){
console.log(ARE.test(testArr[i]))
}
// 预期结果为 true true true
// 实际结果为 true false true
原因
第一次循环过正则匹配到后 正则对象ARE的lastIndex为:第一次字符串的长度 - 1=2。
第二次循环的从下标为2开始,找不到lastIndex重置为0。
第三次重复第一次
为什么第一次lastIndex不重置为0呢?
因为它声明的是上一次匹配文本之后的第一个字符的位置。而当方法 exec() 或 test() 再也找不到可以匹配的文本时,它们会自动把 lastIndex 属性重置为 0。(具体请看上面的说明或者官方文档)
解决方法
1、在每次循环之前重置正则对象ARE的lastIndex值为0
const ARE = /aaa/g
const testArr = ['aaa','aaa','aaa']
for(let i = 0; i < testArr.length; i++){
ARE.lastIndex = 0
console.log(ARE.test(testArr[i]))
}
// 预期结果为 true true true
2、在每次循环都新生成一个对象
//const ARE = /aaa/g
const testArr = ['aaa','aaa','aaa']
for(let i = 0; i < testArr.length; i++){
console.log(/aaa/g.test(testArr[i]))
}
// 预期结果为 true true true
3、在不是必须使用 g的情况下去掉 修饰符g,lastIndex就会不被使用
const ARE = /aaa/
const testArr = ['aaa','aaa','aaa']
for(let i = 0; i < testArr.length; i++){
console.log(ARE.test(testArr[i]))
}
// 预期结果为 true true true