denysdovhan / wtfjs

🤪 A list of funny and tricky JavaScript examples
http://bit.ly/wtfjavascript
Do What The F*ck You Want To Public License
34.6k stars 2.54k forks source link

test() + regex with fullwidth comma #322

Open endenwer opened 6 months ago

endenwer commented 6 months ago
const regexp = /[\uFF00-\uFFEF]/g
console.log(regexp.test(','))
console.log(regexp.test(','))
true
false

When you use a regex with these flags, the .test() method internally updates the lastIndex property of the RegExp object. The lastIndex is where the next search starts. After the first execution of .test(), the lastIndex is updated to the end of the last match. So, the next time .test() is invoked, it continues from the lastIndex.

In the code:

  1. The regular expression /[\uFF00-\uFFEF]/g matches Unicode characters in the range FF00 to FFEF.
  2. With the first call regexp.test(',') (where ',' is the Unicode character FF0C), it matches in this range, so the method returns true, and the lastIndex property of the regex is set to the end of the string.
  3. On the second call regexp.test(','), the search starts from the end of the string (as per lastIndex), so there isn't anything to match, hence it returns false and resets lastIndex back to 0 for the next search.

Therefore, to continually get true from the .test() method, you have to reset the lastIndex manually every time after using the .test() method.

Here is a modification of the code that should work as intended:

const regexp = /[\uFF00-\uFFEF]/g;
console.log(regexp.test(',')); // output: true
regexp.lastIndex = 0; // reset lastIndex
console.log(regexp.test(',')); // output: