乐趣区

关于前端:js在循环中使用正则失效异常的坑

1、异样案例:

应用正则匹配 111

    const regular = /111/g; // 匹配 111
    // console.log(regular.test('111')); // true 匹配胜利
    // console.log(regular.test('111,111')); // true 匹配胜利

    const list = [
        '111',
        '111',
        '111,111',
        '111,111'
    ];
    list.forEach((element, index) => {
        // 异样写法
        console.log('log_________' + regular.test(element));
    });  
    // 打印后果 
    // log_________true
    // log_________false // 会存在正则匹配为 false 的异样
    // log_________true
    // log_________true

why? 首先去 MDN 看了看正则的根底概念。
发现了 lastIndex 这个属性。

2、起因剖析

    用正则表达式只有设置了全局匹配标记 /g,test()办法 的执行就会扭转正则表达式 lastIndex 属性。再循环中间断的执行 test() 办法,前面的执行将会从 lastIndex 数字处开始匹配字符串。
原来如此,看来 test() 办法的确也不能轻易滥用。
确认验证一下:

    const regular = /111/g; // 匹配 111

    const list = [
        '111',
        '111',
        '111,111',
        '111,111'
    ];
    list.forEach((element, index) => {
        // 异样写法
        console.log('log_________' + regular.test(element));
        // 打印 lastIndex
        console.info('logLastIndex___' + regular.lastIndex); 
    });  
    // 打印后果 
    // log_________true
    // logLastIndex___3
    // log_________false  // 的确因为 lastIndex 为 3 导致的
    // logLastIndex___0
    // log_________true
    // logLastIndex___3
    // log_________true
    // logLastIndex___7

3、解决办法 1

下面咱们发现正则 test()办法有 lastIndex 属性,每次循环给复原一下。

    const regular = /111/g; // 匹配 111
    const list = [
        '111',
        '111',
        '111,111',
        '111,111'
    ];
    list.forEach((element, index) => {
        regular.lastIndex = 0;
        console.log('log_________' + regular.test(element)); // 打印失常
    });  

问题解决 OK 了。

3、解决办法 2

下面咱们发现正则表达式设置了全局标记 /g 的问题, 去掉 / g 全局匹配。(这个具体还得看本人的利用场景是否须要 /g)

    const regular = /111/; // 去掉 / g 全局匹配
    const list = [
        '111',
        '111',
        '111,111',
        '111,111'
    ];
    list.forEach((element, index) => {console.log('log_________' + regular.test(element)); // 打印失常
    });  

OK 了。

3、解决办法 3

js 有根本数据类型和援用数据类型
ECMAScript 包含两个不同类型的值:根本数据类型和援用数据类型。\
根本数据类型:Number、String、Boolen、Undefined、Null、Symbol、Bigint。\
援用数据类型:也就是对象类型 Object type,比方:对象(Object)、数组(Array)、函数(Function)、日期(Date)、正则表达式(RegExp)。

so 正则表达式属于援用数据类型,按传统思维必定是须要“深拷贝”的,须要 new 一个新 Object。

    const regular = /111/g;
    const list = [
        '111',
        '111',
        '111,111',
        '111,111'
    ];
    list.forEach((element, index) => {// 正确写法 new RegExp 的内存指向在循环过程中每次都独自开拓一个新的“对象”,不会和前几次的循环 regular.test(xxx)扭转后果而混同
        // console.log('log_________' + /111/g.test(element)); // 这样写当然也行
        console.log('log_________' + new RegExp(regular).test(element)); // 打印 OK 了
    });  
    

OK 了。

退出移动版