1. 程式人生 > 實用技巧 >【要命的神奇bug】if條件 使用 正則表示式

【要命的神奇bug】if條件 使用 正則表示式

今天在做一個輸入判斷,使用了正則,因為多處會用到,所以用了一個全域性變數來接收,這也沒問題
然後,出現了一個神奇的事情,我輸出正則表示式的結果為false,但是if的判斷卻走了true???? WTF????

程式碼大致如下

    // 判斷密碼正則
    const passwordPatern = /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[\!\@\#\$\%\^\*\(\)])[a-zA-Z0-9\!\@\#\$\%\^\*\(\)]{8,17}$/g

    // 判斷密碼
    let tm
    esui.get('password').on('input', function () {
        clearTimeout(tm)
        // 節流
        tm = setTimeout(() => {
            console.log(this.getValue(), passwordPatern.test(this.getValue()))
            if (passwordPatern.test(this.getValue())) {
                console.log('1')
            }
            else {
                console.log('密碼不符合要求')
            }

        }, 800);
    })

密碼符合要求應該會輸出1
測試結果卻出人意料,console明明輸出了true,密碼符合要求,卻走了else,WTF!!! 這就令人匪夷所思了

難道if的判斷有bug?經過多次試驗測試,if(false)肯定不會執行,使用一個變數接收正則判斷的結果後,也不會出現那個問題

所以,這應該是正則表示式的問題

那麼,正則表示式有什麼問題呢,經過進一步測試,passwordPatern.test('q123456!')的結果不是固定的,一會兒為true,一會兒為false

我知道滑鼠放上去會執行一次js獲取結果,所以大膽的想一想,這個正則的執行結果會變,但是又覺得不科學啊
又寫了一個簡單的測試用例

const exp = /abc/g

console.log(exp.test('abc'))
console.log(exp.test('abc'))
console.log(exp.test('abc'))

這個會輸出3個true嗎?
輸出結果

為什麼會輸出false呢?這就是正則的一個特性了(坑坑坑)
去搜索了一圈,在MDN的網站上,找到這麼一句:

test called multiple times on the same global regular expression instance will advance past the previous match.

因為例子中的正則帶了g,所以每次呼叫test方法會先獲取一個隱藏屬性lastIndex,會跳過上次已經搜尋過的部分。

第偶數次呼叫test的時候,就從前一次的lastIndex開始搜尋。結果搜不到,就返回false。lastIndex置為0,下一次呼叫時,就又能搜到了。