What are Zero-Width Assertions?
Most regex patterns consume characters — matching abc advances the cursor three positions. Zero-width assertions match a position in the string without consuming characters. They let you say "match X only when surrounded by Y" without including Y in the result.
Positive Lookahead: (?=...)
Matches a position followed by a specific pattern, without including that pattern in the match.
"16px 2rem 8px".match(/d+(?=px)/g)
// → ["16", "8"] — "px" is checked but not captured
Negative Lookahead: (?!...)
// Password must have uppercase, lowercase, and a digit
/^(?=.*[a-z])(?=.*[A-Z])(?=.*d).{8,}$/.test("MyPass1word") // → true
// Match "foo" only when NOT followed by "bar"
"foobar foobaz".match(/foo(?!bar)/g) // → ["foo"] (only in "foobaz")
Positive Lookbehind: (?<=...)
"Price: $42.50, $100".match(/(?<=$)d+.?d*/g)
// → ["42.50", "100"] — "$" is checked but not captured
Negative Lookbehind: (?<!...)
"wildcat housecat".match(/(?
Practical Examples
// Remove leading zeros
"007 042 100".replace(/(?<=^|s)0+(?=d)/g, "")
// → "7 42 100"
// Split on commas not inside parentheses
"a,b,(c,d),e".split(/,(?![^(]*))/)
// → ["a", "b", "(c,d)", "e"]
Browser Support
Lookbehind was added in ES2018: Node.js 10+, Chrome 62+, Firefox 78+, Safari 11.1+. Not in Internet Explorer. Lookahead has been supported since the earliest JavaScript engines.