tags:

views:

47

answers:

1

I'm confused:

function is_valid(name) {
    var regexp_name = /^(\d|\w)*$/gi;
    return regexp_name.test(name);
}

// Console
console.log(is_valid("Test"));
=> true

console.log(is_valid("Test"));
=> false

console.log(is_valid("Test"));
=> true

console.log(is_valid("Test"));
=> false

What am I doing wrong?

+6  A: 

Remove the /g flag.

The RegExp object is somehow reused. When the /g flag is present, the regex engine will start from the previous matched location until the whole string is consumed.

 1st call:       Test
                 ^
 after 1st call: Test   (found "Test")
                     ^
 2nd call:       Test
                     ^
 after 2nd call  Test   (found nothing, reset)
                 ^

BTW, \w is equivalent to [0-9a-zA-Z_] in Javascript. Therefore, the \d| and the /i flag are redundant. And since you're not using the captured group, there's no need to keep the (…). This following is enough:

var regexp_name = /^\w*$/;
KennyTM
yeah removing it makes the regexp works fine.
thephpdeveloper
Ok, but why? How about an explanation?
George Marian
I'm not understanding why it isn't consuming the entire string. The match is to the end of the string.
George Marian
@George: `$` is only an assertion. It won't consume anything. An empty string at the end is a possible match. Try using `var re = /\w*/g; return re.exec(name);`. You'll see the empty string is matched in the end.
KennyTM
Yes, that works!
Poru
@KennyTM Ah, yes I see. That makes sense. Thanks.
George Marian
It's alternating between true to false because the regex object is reused as @KennyTM said. The `g` flag makes the `lastIndex` property (where to begin next search) jump from `0` (true - always finds a match - `"Test"`) to `4` (false - no matches from here onwards). Wrote some tests on this [answer](http://stackoverflow.com/questions/3152452/unexpected-javascript-behaviour-issue/3152837#3152837) to confirm this behavior.
Anurag