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

问题描述 投票:2回答:1

这个问题在这里已有答案:

在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"

我在这里弄错了什么?

javascript regex es6-class
1个回答
3
投票

来自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(),将不会从您尝试匹配的字符串的开头开始匹配正则表达式。因此,当您第一次尝试匹配字符串“*”时,它将返回true,因为它从该字符串的开头开始搜索。

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

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

这里的解决方案是使用单词的匹配方法来测试正则表达式,而不是使用正则表达式来测试单词。

所以,如果你更换

return this.expression.test(word);

通过

return word.match( this.expression );

一切都会按预期工作,你会得到字符串“kitten3”。

编辑:或者你可以重写正则表达式,根本不使用全局标志。

© www.soinside.com 2019 - 2024. All rights reserved.