js正則全域性匹配引發的血案

wendell.w發表於2020-09-27

現象

  • 下面這個程式碼的輸出毫無疑問,是true;

    const reg = /\d+/g;		//匹配數字
    reg.test(11111);		// true	
    
  • 如果我接著再test一遍呢

    const reg = /\d+/g;		//匹配數字
    reg.test(11111);		// true	
    reg.test(11111);		// false	
    

    這就是血案本案了

  • lastIndex觀察

    const reg = /\d+/g;		//匹配數字
    console.log(reg.test(11111), reg.lastIndex);	// true, 0
    console.log(reg.test(11111), reg.lastIndex);	// false, 5
    console.log(reg.test(11111), reg.lastIndex);	// true, 0
    console.log(reg.test(11111), reg.lastIndex);	// false, 5
    console.log(reg.test(11111), reg.lastIndex);	// true, 0
    console.log(reg.test(11111), reg.lastIndex);	// false, 5
    
    
  • MDN中對於exec和test有如下介紹

    在設定了 global 或 sticky 標誌位的情況下(如 /foo/g or /foo/y),JavaScript RegExp 物件是有狀態的。他們會將上次成功匹配後的位置記錄在 lastIndex 屬性中

  • 處理方案1
    避免在test時使用g(廢話);

  • 處理方案2
    每次test建立新的正則物件 :

    /\d/g.test(11111)		// true
    /\d/g.test(11111)		// true
    /\d/g.test(11111)		// true
    /\d/g.test(11111)		// true
    

    這其實也不太好,每次都例項化出一個新的正則物件;

  • 處理方案3
    lastIndex是可寫的!!
    那就可以這樣了:

    const reg = /\d+/g;		//匹配數字
    reg.test(11111);		// true	
    reg.lastIndex = 0;
    reg.test(11111);		// true	
    

    目前想到的就這三種,後面有想到其它的再來補吧;

相關文章