js正则表达式" /(\ s | \ uFEFF | \ xA0)+ $ /"让firefox和chrome忙碌

时间:2015-07-21 07:39:01

标签: javascript regex google-chrome firefox

当我尝试调用CrossUI(一个js框架)的函数来rtrim由jQuery作为grep的DOM的文本内容时,firefox和chrome将运行到busy。 我发现源代码中的这个正则表达式阻止了浏览器。 我试过/[\s\uFEFF\xA0]+$/并且它有效。 为什么/(\s|\uFEFF|\xA0)+$/被卡住了?他们之间的内在差异是什么?



$('body').text().replace(/(\s|\uFEFF|\xA0)+$/, "");
alert('pass');

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div>
    <div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div>
    <div>a</div>
</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:3)

字符集/[aa]/等同于/[a]/:它是一个集合,假设每个元素只能出现一次(并且忽略额外的元素)。这一切都可以,因为每个选项只有一个字符 - 没有出现复杂的空间。

但是,如果失败,交替/(a|a)/需要检查每个分支,以防万一,因为它不能保证一个分支对另一个分支的决定不会产生后果。交替不保证固定宽度,它不保证捕获组的不变性等。在这种情况下,是的,两个分支是相同的;但是regexp引擎没有检查这个。

因此,如果你有/[aa]+$/并且正在检查aaaaX,那么在匹配失败之前,由于非字符串结束,你有四个检查,每个字符一个,与/[a]+$/(实际上与/a+$/相同)。但是对于/(a|a)+$/,您需要检查2 * (1 + 2 * (1 + 2 * (1 + 2)))次检查,共计30次,因为每个分支都会被检查。对于字符串中的每个额外a,您的时间加倍,因为引擎需要检查a分支以及a分支(!)以查看其中一个,奇迹般地,设法匹配。

所以将此问题应用于您的问题。如评论中所述,您在一个分支中有\xA0,它也隐含在\s中;因此/(\s|\uFEFF|\xA0)+$/将在不在字符串末尾的空白序列中的每个&nbsp;上加倍执行时间。 (实际的rtrim部分,即被替换的部分,不会造成问题 - 字符串空白序列的结束没有任何延迟,作为第一个测试分支,全部{{1成功但不回溯。)

答案 1 :(得分:3)

根据ECMA 5.1 specification\s包括WhiteSpace LineTerminator ,而 WhiteSpace 包括U + FEFF和U + 00A0 in它的定义。

一个简单的测试

/^\s+$/.test("\ufeff\u00a0")

显示IE9和最近版本的Firefox(38)和Chrome(43)遵循这两个字符的规格。如果您决定放弃对旧浏览器的支持,则无需手动将这些字符添加到正则表达式中。只需使用\s

如果您需要在旧浏览器中支持它们,请将它们包含在角色类中:

[\s\ufeff\u00a0]

使用交替将导致ECMA 5.1兼容浏览器中的灾难性回溯。由于交替创建了一个选择点,以回溯 1 并且\s匹配ECMA 5.1中的U + 00A0,\s中的\xA0\s|\uFEFF|\xA0呈现2有效选择匹配一个不间断空间。如果有一串连续的空格(由\s定义),则需要检查O(2 n )个案,其中n是不间断空格的数量。上述子串。同样适用于\ufeff,但这种角色大量出现的情况更为罕见。

相反,字符类不会为回溯创建选择点,因此可以安全地在新旧浏览器中使用。

1 从技术上讲,允许引擎将问题中的交替重写为字符类。但是,它在实践中并不常见,因为它使引擎的实现变得复杂。