/^/
MediumProgramming5 min read

JavaScript Comment Regex

Detects a JavaScript comment, either a single-line // comment or a block /* ... */ comment, using a lazy quantifier on the block form so it stops at the first closing */ instead of the last one.

#javascript#comment#programming#syntax#lazy-matching

Regex Pattern

\/\/.*|\/\*[\s\S]*?\*\/

Pattern Breakdown

Hover over a token to see what it does.

\/\/.*|\/\*[\s\S]*?\*\/
TokenMeaning
\/\/The literal opening delimiter of a single-line comment: two forward slashes
.*The rest of the line; . naturally stops at the first newline, which already matches how line comments end
|Alternation: match either the single-line form on the left or the block form on the right
\/\*The literal opening delimiter of a block comment: a slash followed by an escaped asterisk
[\s\S]*?Any characters at all, including newlines, matched lazily so the block stops at the nearest closer
\*\/The literal closing delimiter of a block comment: an escaped asterisk followed by a slash

Detailed Explanation

What it does

This pattern matches either kind of JavaScript comment: a // line comment that runs to the end of the current line, or a /* */ block comment that can span multiple lines. The block alternative uses a lazy quantifier so that when a string contains two separate block comments, each is matched independently instead of being merged into one.

Why it works

Line comments naturally terminate at a newline because the . in .* does not match \n, so no laziness is needed there. Block comments, however, can contain anything including newlines, so [\s\S]*? is used instead of a bare .*, and it is made lazy (*?) so the engine stops at the very next */ rather than backtracking all the way to the last */ in the string, which is the classic bug that would silently merge multiple comments (and any real code between them) into a single match.

Common use cases

  • Stripping comments from JavaScript source as a lightweight preprocessing step before minification or analysis
  • Extracting inline documentation or TODO/FIXME markers from source files for tooling or dashboards
  • Building a naive syntax highlighter rule that flags comment spans in an editor
  • Detecting whether a snippet of code contains any comments at all, e.g. in a code-quality or linting check

Edge cases

  • A trailing line comment after code, like const x = 1; // set x, matches only the // set x portion since .* stops at end of line
  • A multi-line block comment, like /* line one\nline two */, matches in full because [\s\S] includes newlines
  • Two adjacent block comments, /* a *//* b */, are matched as two separate comments under the global flag because the lazy quantifier stops at the nearest */
  • A URL embedded in a string literal, like "https://example.com", is incorrectly matched by the // alternative because the regex has no awareness of string-literal context, a classic false positive of naive comment-stripping regexes

Limitations

  • Cannot distinguish real comments from '//' or '/*' sequences that appear inside string literals, template literals, or regular expressions, causing false positives (e.g. matching part of a URL like https://example.com)
  • Does not handle nested template literals containing ${...} expressions that themselves contain comment-like sequences
  • Regex-based comment stripping is not safe for production tooling; a real JavaScript tokenizer/parser (e.g. Acorn, Babel) should be used wherever correctness matters

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

// comment /* comment */ /* multi line */
3 matches

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const jsCommentRegex = /\/\/.*|\/\*[\s\S]*?\*\//;
console.log(jsCommentRegex.test('/* note */')); // true

// Careful: this naive regex also matches '//' inside URLs in strings!

Common Mistakes

Using a greedy quantifier for the block comment, /\*[\s\S]*\*/, which spans from the first /* to the LAST */ in the file, merging multiple comments and real code between them

Fix: Use the lazy quantifier *? on the block alternative so each comment is matched independently

Assuming this regex safely strips comments from real source files, then being surprised when it corrupts a string containing '//' (like a URL) or '/*' inside a template literal

Fix: Use an actual JavaScript parser/tokenizer (Acorn, Babel, TypeScript compiler API) for any comment-stripping that needs to be correct on real code

Forgetting that .* in the line-comment branch already stops at a newline, then unnecessarily adding [^\n]* which is redundant

Fix: Rely on the default behavior of . not matching \n instead of adding an equivalent negated class

Performance Notes

  • The alternation tries the // branch first; for long lines with no comment, this branch fails quickly and falls through to the block-comment branch
  • The lazy [\s\S]*? in the block branch can require more backtracking than a greedy version on adversarial input with many stray '*' characters, but remains linear for realistic source files
  • For large files, prefer a single global-flag pass (replace/matchAll) rather than scanning line by line in a loop

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes