← Back to JavaScript Course | Chapter 9: Async & Web APIs | Lesson 22 of 26

JS RegExp Assertions

Lookahead and lookbehind assertions check that a pattern exists (or doesn't) immediately before or after the main match, without actually including that surrounding text in the match result itself -- letting you match 'this word, but only when followed by that other word' without capturing the second word too.

Positive Lookahead: (?=...)

A positive lookahead, written (?=pattern), requires the main match to be immediately followed by the given pattern, but does not include that following text as part of the actual match result -- useful for matching a word only when a specific word comes right after it.

Note: Use lookahead when you need to check for context immediately following a match without that context becoming part of the captured result itself.

Warning: Beginners often expect the lookahead's content to appear in the match result -- it never does, since it is purely a condition, not a capturing part of the pattern.

Example: Positive Lookahead: (?=...)

javascript
console.log("100px".match(/\d+(?=px)/)); // matches digits only when followed by "px"

Negative Lookahead: (?!...)

A negative lookahead, (?!pattern), requires the main match to NOT be followed by the given pattern -- the opposite of a positive lookahead, useful for excluding a specific following context from an otherwise valid match.

Note: Use negative lookahead when a match should be rejected specifically because of what comes right after it, rather than because of the matched text itself.

Warning: A negative lookahead only checks immediately following context -- it cannot express "does not appear anywhere later in the string" on its own without additional pattern structure.

Example: Negative Lookahead: (?!...)

javascript
console.log("100em".match(/\d+(?!px)/)); // matches since NOT followed by "px"

Positive and Negative Lookbehind: (?<=...) and (?<!...)

Lookbehind works like lookahead but checks the text immediately BEFORE the match instead of after -- (?<=pattern) requires that preceding text to be present, and (?<!pattern) requires it to be absent, again without including that preceding text in the actual match result.

Note: Use lookbehind when the context that determines whether a match is valid comes before the text you actually want to capture, rather than after it.

Warning: Lookbehind was added to JavaScript later than lookahead -- while supported in all current major browsers, it is worth being aware of if you must support unusually old browser versions.

Example: Positive and Negative Lookbehind: (?<=...) and (?<!...)

javascript
console.log("$100".match(/(?<=\$)\d+/));  // "100", lookbehind for $
console.log("100".match(/(?<!\$)\d+/));   // "100", not preceded by $

Combining Assertions with the Main Pattern

Assertions are typically combined with a real, capturing part of the pattern -- the assertion establishes context, while the surrounding pattern defines what actually gets matched and returned, together forming a precise condition beyond what plain character matching alone can express.

Note: Think of an assertion as answering "is this the right context?" while the rest of the pattern answers "what exactly do I want to capture here?" -- keeping those two roles distinct clarifies pattern design.

Warning: Overusing multiple chained assertions in one pattern can make it significantly harder to read and debug -- sometimes splitting logic across two separate checks in code is clearer than one dense regex.

Example: Combining Assertions with the Main Pattern

javascript
console.log(/(?=.*\d).{6,}/.test("secret1")); // lookahead checks context, {6,} defines the real match

When Assertions Are the Right Tool

Assertions shine specifically when you need to match based on surrounding context without capturing that context -- extracting a price after a currency symbol, validating a password contains multiple different character types, or finding a word only when it is not part of a larger compound word.

Note: Reach for an assertion specifically when a normal capturing group would include unwanted extra text in your match result.

Warning: For simple cases where including the surrounding context in the match result would be fine (or even useful), a normal group is often simpler than reaching for an assertion.

Example: When Assertions Are the Right Tool

javascript
console.log("Price: $50".match(/(?<=\$)\d+/)); // extracts price after currency symbol without capturing the symbol itself
Common Mistakes
  1. Confusing a lookahead/lookbehind with a normal group -- the text they check against is not included in the actual match result, which surprises people expecting it to be captured.
  2. Mixing up positive assertions (?=...) and (?<=...) (must be present) with negative ones (?!...) and (?<!...) (must NOT be present).
  3. Assuming lookbehind support is universal without checking -- it was added to JavaScript later than lookahead and has slightly different browser support history.
Chapter Summary
  • (?=...) is a positive lookahead: the match must be followed by the given pattern, without including it in the result.
  • (?!...) is a negative lookahead: the match must NOT be followed by the given pattern.
  • (?<=...) and (?<!...) are positive and negative lookbehind, checking what comes before the match instead of after.
Browser Support

Lookahead has been supported in every browser for a very long time; lookbehind is supported in all current major browsers, added somewhat more recently.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.