代码之家  ›  专栏  ›  技术社区  ›  Osman Cea

将表达式定义为类属性[重复]时,Javascript中的正则表达式测试失败

  •  2
  • Osman Cea  · 技术社区  · 6 年前

    在ES6中将正则表达式定义为类属性时,我发现了这种非常奇怪的行为。我目前在使用typescript和angular时遇到了这种行为,但我在chrome控制台中制作了一个剥离版本,结果是一样的。

    class RegexTest {
      constructor() {
        this.expression = /[\*|\-|\_]/g;
      }
    
      testStringExpression(word) {
        return this.expression.test(word);
      }
    }
    
    const tester = new RegexTest();
    const words = "*, *, *, kitten";
    
    const reduced = words.split(',').reduce((acc, item, index) => {
      if ( tester.testStringExpression(item) ) {
        return acc;
      } else {
        return acc + item + index;
      }
    }, "");
    
    console.log(reduced); // Should be " kitten3", instead I'm getting " *2 kitten3"
    

    但是,如果我只是在reduce中测试正则表达式,结果是预期的:

    const words = "*, *, *, kitten";
    const reduced = words.split(',').reduce((acc, item, index) => {
      if ( /[\*|\-|\_]/g.test(item) ) {
        return acc;
      } else {
        return acc + item + index;
      }
    }, "");
    
    console.log(reduced); // " kitten3"
    

    我到底做错了什么?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Shilly    6 年前

    从MDN参考:

    If the regex has the global flag set, test() will advance the lastIndex of the regex. A subsequent use of test() will start the search at the substring of str specified by lastIndex (exec() will also advance the lastIndex property).

    所以反复使用 .test() 在同一个regex对象上,不会从尝试匹配的字符串开始匹配regex。因此,第一次尝试匹配字符串“*”,它将返回true,因为它从该字符串的开头开始搜索。

    由于表达式是类的属性,因此再次重用相同的正则表达式,第二次从发送它的字符串的结尾开始,而不是从开头开始。所以当你尝试匹配“*”时,你会得到false而不是true。

    通过将正则表达式内联,每次都会创建一个新的regex对象,因此不会更新lastIndex。

    这里的解决方案是使用单词匹配方法来测试regex,而不是使用regex来测试单词。

    所以如果你更换

    return this.expression.test(word);

    通过

    return word.match( this.expression );

    一切都会如你所愿,你会得到字符串“kitten3”。

    编辑:或者您可以重写regex,完全不使用全局标志。