Par*_*ham 4 javascript regex browser
据我所知[ab],(a|b)在尝试匹配一组字符时应该是有目的的.现在,看看两个正则表达式:
/^(\s|\u00A0)+|(\s|\u00A0)+$/g
/^[\s\u00A0]+|[\s\u00A0]+$/g
Run Code Online (Sandbox Code Playgroud)
它们都应该匹配字符串开头和结尾的空格(有关正则表达式本身的更多信息,请参阅Polyfill 这里的部分).当使用方括号时,一切都运行良好,但是当你切换到括号时,即使是最简单的字符串也会导致浏览器无限期地运行.这种情况发生在最新的Chrome和Firefox上.
这个jsfiddle演示了这个:
a ="a b";
// Doesn't work
// alert(a.replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g,''));
// Works
alert(a.replace(/^[\s\u00A0]+|[\s\u00A0]+$/g,''));
Run Code Online (Sandbox Code Playgroud)
这是一个疯狂的怪癖与浏览器的正则表达式引擎的实现或还有其他关于正则表达式的算法导致这个?
您所看到的问题称为灾难性的回溯,如解释在这里.
首先,让我简化并澄清您的测试用例:
a = Array(30).join("\u00a0") + "b"; // A string with 30 consecutive \u00a0
s = Date.now();
t = a.replace(/^(\s|\u00A0)+$/g, '');
console.log(Date.now()-s, a.length);
Run Code Online (Sandbox Code Playgroud)
发生的事情是表达的第二部分:^(\s|\u00A0)+$.请注意,它\s匹配许多空白字符,包括\u00A0它自己.这意味着这两个\s和\u00A0匹配各30个的\u00A0字符.
因此,如果您尝试匹配字符串/(\s|\u00A0)+/,您会发现2^3030个字符的空白模式的每个不同组合将导致匹配.当正则表达式匹配器匹配前30个字符时,它将尝试匹配string($)的结束并失败,因此它会回溯并最终尝试所有2^30组合.
您的原始字符串(在jsfiddle中,其中stackflow中的一个已经"规范化"到所有空格)a \u00a0 \u00a0 ... \u00a0 b大约有30个\u00a0字符,因此浏览器大致2^30需要完成.它不会挂起浏览器,但需要几分钟才能完成.