元素标签名的正则表达式有 bug 吗?

3
简单的问题,有人能向我解释一下吗? http://jsfiddle.net/paj5c4wn/4/
// check body tagname, return bool
var check = (function ()
{
    var body = /body/gi;

    return function ( str )
    {

        return body.test( str );
    }

})();

// get body element
var body = document.body;

// display result
for ( var i = 0; i < 10; i++ )
{
    document.getElementById( 'result-' + i ).innerHTML = check( body.tagName );
}

使用:

<p id="result-0" ></p>
<p id="result-1" ></p>
<p id="result-2" ></p>
...

做:

true

false

true

false

...

怎么可能呢?

下面的答案提供了解决问题的好方法 - 通过在闭包中删除body变量。然而,你看到的是由于正则表达式中的g标志引起的。 - nhahtdh
1个回答

6
有两种可能的解决方案:
  1. 您的代码总是使用相同的引用来访问变量body。再加上正则表达式中的global标志,RegExp.prototype.test()会记录并使用正则表达式最后匹配的索引开始搜索。

    首先,/body/gi在for循环的第一次迭代中匹配'BODY',返回true。然后,在第二个函数调用时,它从索引4开始匹配字符串。因此,它从'BODY'字符串的末尾开始匹配,显然导致没有匹配,返回false。然后由于该字符串以前没有匹配过,索引在第三个测试中被重置,整个过程重复。

    为了解决这个问题,您可以在闭包中删除body变量,使每次函数调用都可以创建一个新的正则表达式对象,每个对象的初始索引为0。

  2. 您可以简单地删除global标志,因为这个特定的匹配只需要执行一次。没有g标志,JavaScript正则表达式对象将不会保留最后一个索引,而是在每次执行后自动重置索引为0。

将两种选项组合在一起即可(因为在这种情况下,全局标志是不必要的):

// check body tagname, return bool
var check = (function ()
{
    return function ( str )
    {

        return /body/i.test( str );
    }

})();

// get body element
var body = document.body;

// display result
for ( var i = 0; i < 10; i++ )
{
    document.getElementById( 'result-' + i ).innerHTML = check( body.tagName );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接