美文网首页
js在循环中使用正则失效异常的坑

js在循环中使用正则失效异常的坑

作者: 天渺工作室 | 来源:发表于2023-04-28 23:11 被阅读0次

    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了。

    相关文章

      网友评论

          本文标题:js在循环中使用正则失效异常的坑

          本文链接:https://www.haomeiwen.com/subject/vjnwjdtx.html