3
var matches;

while(matches = /./g.exec("abc"))
{
    console.log("hey");
}

This never terminates. I expect it to terminate after 3 loops.

Warning: Don't run it in Chrome because the infinite log lines freeze your entire system. It's safe to run it in IE (it still freezes your webpage but you can go to the location bar and press enter to reload).

3
  • matches = /./g.exec("abc") will return ['a'] which is a truthy value in JS, hence it runs into an infinite loop. It's like while(true){ // dosomething } . As the condition evaluates to true in every iteration, it will never break Commented Oct 8, 2015 at 12:37
  • @Arkantos When you use the g flag, each iteration is supposed to start where the previous one ended. Commented Oct 8, 2015 at 12:38
  • @Barmar, but, as you use a regexp literal in the test part of the loop, it will create a regexp each time you want the test, and compile it, and execute it on the string "abc" with a fresh regexp each time. For sure this is not what was intended, but you have to observe where the regexp is created and compiled. Even if javascript optimices this to create and compile the regexp only once, the matching status or history must be renewed each time you go through the test. Commented Oct 10, 2015 at 12:07

2 Answers 2

11

This is how you should execute exec in a loop:

var matches;        
var re = /./g;

while(matches = re.exec("abc")) {
  if (matches.index === re.lastIndex)
     re.lastIndex++;
  console.log("hey");
}
  • Keep regex in a separate variable rather than using regex literal.

  • Also if lastIndex (matched position) of regex is same as index property of resulting array then increment lastIndex by 1.

Sign up to request clarification or add additional context in comments.

4 Comments

You only need to do the increment if you're using a regexp that can match a zero-length string.
Thanks. Keeping it in a separate variable was the solution. However I don't understand, why do I need to increment lastIndex? exec() does that for me.
@StefanMonov It will put it past the end of the last match. But if the regexp can match a zero-length string, it will get stuck at that point and keep matching that same empty string.
@Barmar I had this problem. Changing my RE to no longer match empty strings worked a treat. Thanks
5

It's because you are creating a new object with the g flag every time, instead of keeping one regex object. The regex object keeps track of the last match. Since you are creating new objects every time, the object starts from the beginning.

Each regex literal is it's own object that's why:

/./g !== /./g

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.