我在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"
我在这里犯错了什么?
答案 0 :(得分: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”。
编辑:或者你可以重写正则表达式,根本不使用全局标志。