Explain Codes LogoExplain Codes Logo

Javascript regex returning true.. then false.. then true.. etc

javascript
regex-engineering
javascript-best-practices
regex-pitfalls
Nikita BarsukovbyNikita Barsukov·Oct 9, 2024
TLDR

Seeing alternating true/false outcomes from a regex test? The global (g) flag could be your culprit here. JavaScript's global regex advances the lastIndex upon every call, altering the starting point for the next search, leading to flip-flop results. Here's how to solve it:

First, you could remove the g flag:

var regex = /your-pattern/; // Where's Waldo (g)? Nowhere. var result = regex.test("your-string"); // Hulk: That's my secret, Cap. I'm always consistent.

Or if you want to use global regex again and again, reset lastIndex prior:

var regex = /your-pattern/g; // Had a g-reat time; let's do it again sometime! regex.lastIndex = 0; // Back to square one, compadre! var result = regex.test("your-string"); // The results don't lie.

Remember: think twice before going global for single tests, and always reset lastIndex before retests to avoid funky behaviour.

Unraveling the mystery: regex state and the 'g' flag

The global g flag makes regex act like a poker player - it keeps its cards (or states) close to its chest between calls. This means the regex lastIndex stays tucked away, leading to Jekyll-and-Hyde results for your matching capers.

Hidden treasure: lookahead and lookbehind assertions

For a greater degree of accuracy (or to feel like a regex private eye), you might want to take advantage of lookaheads ((?=...) and (?<!...)) and lookbehinds ((?<=...) and (?<!...)). These guys allow you to validate conditions without affecting your match or move forward.

Take care when you're using newer regex features like lookbehind assertions, as browser support can be as predictable as a bowl of alphabet soup. Double-check with resources like Can I use or MDN, and ensure you're not leaving older browsers in the dust.

Getting surgical with character matching

When we're talking input validation, such as usernames or passwords, character ranges in your regex are like a surgeon’s scalpel – the sharper and more precise, the better:

  • [a-zA-Z0-9] means you're accepting the alphabet and digits at your party.
  • Fancy lowercase letters, digits, and even the lonely hyphen and underscore? [a-z0-9_-] has got your back!
  • Ensure - is at the start or end to avoid it being mistaken for an anti-socialite.
  • \w is your best friend if you need a pattern that reads alphanumeric characters and underscores (but remember it's not picky about case).

Caution: common regex pitfalls

The range illusion

A word of caution on ranges such as [a-z]. [a-b-c] will leave you scratching your head as the extra - acts as a range operator. So beware of mischievous metacharacters!

The mischievous quantifier

Place those quantifiers in the right spot. For example, a?b matches 'b' or 'ab', not 'a'. Misplaced quantifiers can be sneakier than Loki in a mask.

Case sensitivity sneak attack

Your regular expressions in JavaScript are case-sensitive by default. Apply the i flag for peace, love and harmony (i.e., ignoring case). Alternatively, invite both cases to your character party with care.