使用/ g修饰符和eval的正则表达式文字和FireFox和Chrome中的奇怪行为

时间:2010-09-19 22:40:33

标签: javascript regex firefox google-chrome

我在某些javascript代码中遇到了一些奇怪的行为,但仅限于Firefox和Chrome。 IE很好。

我已经隔离了问题并创建了一个小页面,以便您可以自己查看行为。

基本上,似乎在方法调用MethodC中重用 MethodC 中的正则表达式对象,即使它是局部变量。有人可以解释这种行为吗?

<html>
<head>
<script type="text/javascript">
    function RunDemo()
    {
        var subject = "01234 555 6789";

        for (var i = 1; i <= 10; i++) {
            MethodA(subject, i);
            MethodB(subject, i);
            MethodC(subject, i);
        }
    }

    // OK, OK, OK, OK, OK, OK, OK, OK, OK, OK
    function MethodA(subject, iteration)
    {
        var myRegexp = new RegExp("5", "g");
        var matches = myRegexp.exec(subject);
        AddItem(matches ? "OK" : "no match", "listA");
    }

    // OK, OK, OK, OK, OK, OK, OK, OK, OK, OK
    function MethodB(subject, iteration)
    {
        var myRegexp = /5/;
        var matches = myRegexp.exec(subject);
        AddItem(matches ? "OK" : "no match", "listB");
    }

    // OK, OK, OK, no match, OK, OK, OK, no match, OK, OK (in FireFox and Chrome, IE is fine)
    function MethodC(subject, iteration) {
        var myRegexp = /5/g;
        var matches = myRegexp.exec(subject);
        AddItem(matches ? "OK" : "no match", "listC");
    }

    function AddItem(itemText, listID) {
        var li = document.createElement("li");
        li.innerHTML = itemText;
        document.getElementById(listID).appendChild(li);
    }   

</script>
</head>
<body onload="RunDemo()">
    <h2>Method A</h2>    
    <ul id="listA"></ul>

    <h2>Method B</h2> 
    <ul id="listB"></ul>

    <h2>Method C</h2> 
    <ul id="listC"></ul>
</body>
</html>

4 个答案:

答案 0 :(得分:3)

V8和spidermonkey中的优化器在看到正则表达式文字并重用它时会创建一个正则表达式对象。

根据ECMA3,这是合规行为,但在ECMA5中将不合规。

  

7.8.5正则表达式文字

     

正则表达式文字是一个输入元素,当它被转换为RegExp对象时(第15.10节)   扫描。在评估包含程序或函数开始之前创建对象。评价   literal生成对该对象的引用;它不会创建新对象。一个中的两个正则表达式文字   程序计算到正则表达式对象,即使两个文字相对,也永远不会相互比较为===   内容相同。 RegExp对象也可以在运行时由新的RegExp(第15.10.4节)或调用创建   将RegExp构造函数作为函数(第15.10.3节)。

     

ECMAScript语言规范第3版

比较:

  

7.8.5正则表达式文字

     

正则表达式文字是一个输入元素,每次转换为RegExp对象(见15.10)   文字被评估。程序中的两个正则表达式文字计算为正则表达式对象   即使两个文字的内容相同,也绝不相互比较===。 RegExp对象也可以   可以在运行时通过新的RegExp创建(参见15.10.4)或将RegExp构造函数作为函数调用(15.10.3)。

     

ECMAScript语言规范第5版

以下是一些解决方法:

  • 请勿将/g标记与exec一起使用。
  • 从RegExp构造函数而不是regexp文字创建一个RegExp。

我认为,做其中一项或两项都会使问题消失。

答案 1 :(得分:2)

这在Mozilla Javascript参考中有所提及:

  

如果你的正则表达式使用了   “g”标志,你可以使用exec方法   多次找到连续   匹配在同一个字符串中。当你   这样做,搜索开始于   由str指定的str的子字符串   正则表达式的 lastIndex   属性

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp/exec#Description

我不明白为什么在离开MethodC后保留 lastIndex 属性

修改 我发现这个错误似乎很难描述你在这里遇到的问题:https://bugzilla.mozilla.org/show_bug.cgi?id=98409

答案 2 :(得分:2)

Chrome(&amp; FF)中的 lastIndex 属性为 acting as a static variable: alt text


但不是IE: alt text

至于为什么会发生这种情况,我不确定。您可以 work around this

.match()
function MethodC(subject, iteration) {
    var myRegexp = /5/g;
    var matches = subject.match(myRegexp);
    AddItem(matches ? "OK" : "no match", "listC");
}

答案 3 :(得分:0)

当我将变量名称更改为myRegexp1,myRegexp2和myRegexp3时,仍然会发生这种情况,因此您的前提不正确。 FWIW,Firefox 4 beta没有出现问题,只有Chrome。