Back to Home

RegExp.escape() escapes letters and spaces: why

RegExp.escape() escapes Latin letters, digits, and spaces for safe RegExp concatenation. The standard requires this to avoid errors with capture groups and legacy sequences. Recommended to use with u flag and polyfill.

Why does RegExp.escape() hide letters in \x codes?
Advertisement 728x90

# Escaping in RegExp.escape(): Why Letters, Digits, and Spaces Become \x Codes

The RegExp.escape() function, introduced in browsers in 2025, escapes not only regex metacharacters but also Latin letters, leading digits, spaces, and punctuation like @. This sets it apart from traditional hand-rolled escape functions, which ignored such characters. The ECMAScript standard requires this to prevent errors during RegExp concatenation.

Reasons for Escaping Digits and Letters

Leading digits are escaped to avoid interpretation as capture group numbers or octal codes. Latin letters ensure proper handling of escape sequences like \c.

Example with a digit:

Google AdInline article slot
p = '2'
new RegExp('()\\1' + RegExp.escape(p)).source // ()\\1\\x32
new RegExp('()\\1' + p).source // ()\\12

Without escaping, \12 refers to the 12th group or the character with octal code 12. With escaping, it matches group 1 followed by the character 2.

Example with a letter:

p = 'a'
new RegExp('\\c' + RegExp.escape(p)).source // \\c\\x61
new RegExp('\\c' + p).source // \\ca

\ca is interpreted as a control character (code 1), while \c\x61 is the sequence \c followed by a. In Unicode mode (u or v), such constructs trigger a SyntaxError, simplifying debugging.

Google AdInline article slot

Spaces and Punctuation: Preventive Protection

The standard doesn't explain escaping spaces and characters like @. The TC39 repository notes that all characters capable of triggering "context escape" in the future are escaped. This restricts context entry and exit to only spaces or ASCII punctuation.

This approach is controversial: it adds overhead without current necessity. The proposal for an x flag to ignore whitespace is stuck at stage 1 of 4.

Comparison with Hand-Rolled Functions

Classic escape function from MDN (2020):

Google AdInline article slot
function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&');
}

It covers metacharacters but not digits or letters. An improved version that escapes leading digits and hyphens:

function escapeRegExp(string) {
    const coolCmd = string => string.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')
        .replaceAll('-', '\\x2d');
    const charCode = string.charCodeAt(0);
    return charCode >= 0x30 && charCode <= 0x39
        ? `\\x${charCode.toString(16)}${coolCmd(string.slice(1))}`
        : coolCmd(string);
}

| Aspect | RegExp.escape() | Custom (improved) |

|--------------------|------------------|-------------------|

| Leading digits | \x32 | \x32 |

| Latin letters | \x61 | No |

| Spaces/@ | \x20/\x40 | No |

| Performance | Native | RegExp-based |

Usage Recommendations

  • For new code: Use RegExp.escape() with a polyfill for older environments.
  • Unicode mode: Always add the u flag—it catches errors at parse time.
  • ESLint: Enable the @eslint/regexp/no-octal-escape rule and require-unicode-regexp.
// Polyfill not required, but useful
const polyfill = () => {
  RegExp.escape = RegExp.escape || function(s) {
    return s.replace(/[-[\]\/{}()\*+?\.\\^$|]/g, '\\$&');
    // Extend as needed
  };
};

Key Points

  • RegExp.escape() escapes digits/letters for RegExp concatenation, spaces as a precaution.
  • Without the u flag, errors are masked; with it, you get SyntaxError at parse time.
  • Hand-rolled functions are outdated: migrate to the native version with a polyfill.
  • Avoid \cX—it's legacy; use explicit codes instead.
  • The x flag (ignore whitespace) is unlikely.

— Editorial Team

Advertisement 728x90

Read Next