带有元素标记名的错误正则表达式?

bug regexp with element tagname?

简单的问题,谁能给我解释一下?

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

...

怎么可能?

有两种可能的解决方案:

  1. 您的代码始终使用对 body 变量的相同引用。结合正则表达式中的global标志,RegExp.prototype.test()记录并使用正则表达式匹配的最后一个索引开始搜索。

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

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

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

结合这两个选项(因为在这种情况下无论如何都不需要全局标志):

// 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 );
}