bug regexp with element tagname?

71 Views Asked by At

Simple question, someone can explain this to me ?

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

with :

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

do :

true

false

true

false

...

how it's possible ?

1

There are 1 best solutions below

0
On BEST ANSWER

There are two possible solutions:

  1. Your code always uses the same reference to the body variable. Combined with the global flag in the regular expression, RegExp.prototype.test() records and uses the last index that the regex matched to start searching.

    First, /body/gi matches 'BODY' during the first iteration of the for loop, yielding true. Then, on the second function call, it starts matching the string from index 4. Thus, it begins at the end of the 'BODY' string, so it clearly results in no match, returning false. The index then gets reset on the third test since the string did not previously match and the whole process repeats.

    To counteract this, you can remove the body variable in the closure to allow a new regular expression object to be created with each function call, each with an initial index of 0.

  2. You can simply remove the global flag since this particular match only needs to be performed one time. Without the g flag, a JavaScript regular expression object will not preserve the last index. Instead, the index will automatically be reset to zero after each execution.

Combining both options (since the global flag is unnecessary in this case anyway):

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