# The Most Surprising Behavior of JavaScript Regular Expression You Have Ever Seen!

![Regular Expressions](https://gist.githubusercontent.com/myogeshchavan97/e0be7fc4c838544e2d00afeb3a82ae10/raw/d313dd12b4e1d8ba8e876d3f527720e0ce3a8aa6/regex.png)

> JavaScript regular expression objects are stateful when they have the `/g` or `/y` flag in the pattern to match.

When we create a regular expression that has the `/g` flag, it maintains the `lastIndex` property which keeps track of the index where to start finding for the next match. So next time when we start testing using the same pattern, it starts searching from the index it found the last match.

Consider, we have a regular expression like this

```js
const pattern = /ab/g;
```

and you want to find if the pattern is present or not in any of the strings passed, we can do like this

```js
console.log(pattern.test('abcd')) // true
console.log(pattern.lastIndex) // 2
```

It returns `true` because `ab` is present in the string `abcd`.
But as the `lastIndex` property is maintained by the regular expression stored in the variable `pattern` which is `0` initially and becomes `2` when it finds the match at 0th position in the string `abcd`, so when next time we call `test` method, it starts from 2nd position to search for the match and so the match fails.

```js
const pattern = /ab/g;

console.log(pattern.test('abcd')) // true
console.log(pattern.lastIndex) // 2
console.log(pattern.test('abcd')) // false
console.log(pattern.lastIndex) // 0
```

And as it's not able to find string `ab` inside `abcd` starting from position `2`, it resets the `lastIndex` property to `0` so when we again call the method it returns `true`.

```js
const pattern = /ab/g;

console.log(pattern.test('abcd')) // true
console.log(pattern.lastIndex) // 2
console.log(pattern.test('abcd')) // false
console.log(pattern.lastIndex) // 0
console.log(pattern.test('abcd')) // true
```

> This might not be the behavior you expected but this is how regular expression maintains the `lastIndex` property when either using the `test()` or `exec()` method.

This behavior is sometimes useful in some scenarios.

_Suppose you want to find the position of all occurrences of vowels in a string, you can do something like this:_

```js
const source = "This is some text";
const pattern = /[aeiou]/g;
while((result = pattern.exec(source)) !== null) {
  console.log("Character " + result[0] + " found at position " + (pattern.lastIndex - 1));
}

/* output:
Character i found at position 2
Character i found at position 5
Character o found at position 9
Character e found at position 11
Character e found at position 14
*/
```

But this may not be the behavior you always want.
So in that case, you can use the `match()` method of regular expression instead of `test()` or `exec()`.

If you want to use the `test()` method only then you need to reset the `lastIndex` to `0` after every search.

```js
const pattern = /ab/g;
console.log(pattern.test('abcd')) // true
pattern.lastIndex = 0;
console.log(pattern.test('abcd')) // true
```

### Thanks for reading!

Check out my recently published [Mastering Redux](https://master-redux.yogeshchavan.dev/) course.

In this course, you will build 3 apps along with food ordering app and you'll learn:

* Basic and advanced Redux
* How to manage the complex state of array and objects
* How to use multiple reducers to manage complex redux state
* How to debug Redux application
* How to use Redux in React using react-redux library to make your app reactive.
* How to use redux-thunk library to handle async API calls and much more

and then finally we'll build a complete [food ordering app](https://www.youtube.com/watch?v=2zaPDfCKAvM) from scratch with stripe integration for accepting payments and deploy it to the production.

[<img src="https://gist.github.com/myogeshchavan97/98ae4f4ead57fde8d47fcf7641220b72/raw/c3e4265df4396d639a7938a83bffd570130483b1/banner.jpg">](https://bit.ly/3w0DGum)

**Want to stay up to date with regular content regarding JavaScript, React, Node.js? [Follow me on LinkedIn](https://www.linkedin.com/in/yogesh-chavan97/).**

[<img src="https://cdn.buymeacoffee.com/buttons/default-yellow.png" >](https://www.buymeacoffee.com/myogeshchavan97)


