1

NOTE: I faced this issue in real life production application. Though I was able to resolve it, sadly, I don't understand why its behaving like this.

I have this regular expression

// Notice global modified at the end.
const regexExp = /(\d{4})-(\d{2})-(\d{2})T((\d{2}):(\d{2}):(\d{2}))\.(\d{3})Z/g;

// Array of same string 6 times.
[
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
]
.forEach((i) => console.log(regexExp.test(i)));

    // This would print
    // true
    // true
    // false -> Why?
    // true
    // true
    // false -> why?

You can run the code by clicking Run Code snippet. I am baffled as why is it testing false every 3rd time?

Following two solutions tend to work.

  1. Defining the Expression inside the forEach block.

// Array of same string 6 times.
[
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
]
.forEach((i) => {
  const regexExp = /(\d{4})-(\d{2})-(\d{2})T((\d{2}):(\d{2}):(\d{2}))\.(\d{3})Z/g;
  console.log(regexExp.test(i))
});

    // This would print
    // true
    // true
    // true -> Yay!!
    // true
    // true
    // true -> Yay!!

I know why this works, as basically for each block scope, new regex is created. i.e. for each loop, a new regex is created and hence same object is never used for second call.

Method 2: Use i modifier instead of g modified

// Notice global modified at the end.
const regexExp = /(\d{4})-(\d{2})-(\d{2})T((\d{2}):(\d{2}):(\d{2}))\.(\d{3})Z/i;

// Array of same string 6 times.
[
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
  '{"ApplicationDate.Time.DateTime":{"$gte":"2017-08-14T11:27:26.034Z","$lt":"2017-08-24T11:27:26.034Z"}}',
]
.forEach((i) => console.log(regexExp.test(i)));

    // This would print
    // true
    // true
    // true -> Yay!!
    // true
    // true
    // true -> Yay!!

So why is this happening,

  1. why is Method 2 working?

  2. Why it works when I use i modifier and why it does not work with g modifier?

  3. Why every 3rd test? Why not 4th or 5th or any random test?

It seems that when using g modifier mutates the RegExp instance, why is that so?

I would really appreciate if someone can shed some light on this question.

Thanks in advance.

Dave Amit
  • 2,299
  • 12
  • 17

0 Answers0