javascript - js正则如果使用^和$再使用g会很怪异,但不报错

查看:79
本文介绍了javascript - js正则如果使用^和$再使用g会很怪异,但不报错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

var reg1 =  /^1$/g;
var reg2 = /^1$/;
for (var i = 0; i < 10; i++) {
    console.log(reg1.test('1')) // true false true false true false true false ...
    console.log(/^1$/g.test('1')) // true  true  true  true  true  true  true ...
    console.log(reg2.test('1')) // true  true  true  true  true  true  true ...
    console.log(/^1$/.test('1')) // true  true  true  true  true  true  true ...
}

为什么第一条console.log的输出会是这样?

解决方案

正则执行时, RegExp对象的lastIndex可能会改变.

test 方法用于检测一个字符串是否匹配某个正则规则, 只要是字符串中含有与正则规则匹配的文本, 该方法就返回true, 否则返回 false.

实际上, 如果正则表达式带有全局标志(带有参数g)时, test 方法还受正则对象的lastIndex属性影响,如下:

var reg = /[a-z]+/;//正则不带全局标志
console.log(reg.test("abc"));//true
console.log(reg.test("de"));//true

var reg = /[a-z]+/g;//正则带有全局标志g
console.log(reg.test("abc"));//true
console.log(reg.lastIndex);//3, 下次运行test时,将从索引为3的位置开始查找
console.log(reg.test("de"));//false

该影响将在exec 方法讲解中予以分析.

exec 方法用于检测字符串对正则表达式的匹配, 如果找到了匹配的文本, 则返回一个结果数组, 否则返回null.

语法: exec(string)

exec 方法返回的数组中包含两个额外的属性, index 和 input. 并且该数组具有如下特点:

  • 第 0 个项表示正则表达式捕获的文本

  • 第 1~n 项表示第 1~n 个反向引用, 依次指向第 1~n 个分组捕获的文本, 可以使用RegExp.$ + "编号1~n" 依次获取分组中的文本

  • index 表示匹配字符串的初始位置

  • input 表示正在检索的字符串

无论正则表达式有无全局标示"g", exec 的表现都相同. 但正则表达式对象的表现却有些不同. 下面我们来详细说明下正则表达式对象的表现都有哪些不同.

假设正则表达式对象为 reg , 检测的字符为 string , reg.exec(string) 返回值为 array.

若 reg 包含全局标示"g", 那么 reg.lastIndex 属性表示原字符串中匹配的字符串末尾的后一个位置, 即下次匹配开始的位置, 此时 reg.lastIndex == array.index(匹配开始的位置) + array[0].length(匹配字符串的长度). 如下:

var reg = /([a-z]+)/gi,
    string = "World Internet Conference";
var array = reg.exec(string);
console.log(array);//["World", "World", index: 0, input: "World Internet Conference"]
console.log(RegExp.$1);//World
console.log(reg.lastIndex);//5, 刚好等于 array.index + array[0].length

随着检索继续, array.index 的值将往后递增, 也就是说, reg.lastIndex 的值也会同步往后递增. 因此, 我们也可以通过反复调用 exec 方法来遍历字符串中所有的匹配文本. 直到 exec 方法再也匹配不到文本时, 它将返回 null, 并把 reg.lastIndex 属性重置为 0.

接着上述例子, 我们继续执行代码, 看看上面说的对不对, 如下所示:

array = reg.exec(string);
console.log(array);//["Internet", "Internet", index: 6, input: "World Internet Conference"]
console.log(reg.lastIndex);//14

array = reg.exec(string);
console.log(array);//["Conference", "Conference", index: 15, input: "World Internet Conference"]
console.log(reg.lastIndex);//25

array = reg.exec(string);
console.log(array);//null
console.log(reg.lastIndex);//0

以上代码中, 随着反复调用 exec 方法, reg.lastIndex 属性最终被重置为 0.

问题回顾

在 test 方法的讲解中, 我们留下了一个问题. 如果正则表达式带有全局标志g, 以上 test 方法的执行结果将受 reg.lastIndex影响, 不仅如此, exec 方法也一样. 由于 reg.lastIndex 的值并不总是为零, 并且它决定了下次匹配开始的位置, 如果在一个字符串中完成了一次匹配之后要开始检索新的字符串, 那就必须要手动地把 lastIndex 属性重置为 0. 避免出现下面这种错误:

var reg = /[0-9]+/g,
    str1 = "123abc",
    str2 = "123456";
reg.exec(str1);
console.log(reg.lastIndex);//3
var array = reg.exec(str2);
console.log(array);//["456", index: 3, input: "123456"]

以上代码, 正确执行结果应该是 "123456", 因此建议在第二次执行 exec 方法前, 增加一句 "reg.lastIndex = 0;".

若 reg 不包含全局标示"g", 那么 exec 方法的执行结果(array)将与 string.match(reg) 方法执行结果完全相同.

该片段来自 正则表达式前端使用手册 | louis blog 有帮助的话请点个赞吧~

这篇关于javascript - js正则如果使用^和$再使用g会很怪异,但不报错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆