Escapado en RegExp.escape(): Por qué las letras, dígitos y espacios se convierten en códigos \x
La función RegExp.escape(), introducida en los navegadores en 2025, escapa no solo los metacarácteres de regex, sino también letras latinas, dígitos iniciales, espacios y puntuación como @. Esto la distingue de las funciones de escape tradicionales implementadas manualmente, que ignoraban tales caracteres. La norma ECMAScript exige esto para evitar errores durante la concatenación de RegExp.
Razones para escapar dígitos y letras
Los dígitos iniciales se escapan para evitar que se interpreten como números de grupos de captura o códigos octales. Las letras latinas garantizan el manejo correcto de secuencias de escape como \c.
Ejemplo con un dígito:
p = '2'
new RegExp('()\\1' + RegExp.escape(p)).source // ()\\1\\x32
new RegExp('()\\1' + p).source // ()\\12
Sin escapado, \12 se refiere al grupo 12 o al carácter con código octal 12. Con escapado, coincide con el grupo 1 seguido del carácter 2.
Ejemplo con una letra:
p = 'a'
new RegExp('\\c' + RegExp.escape(p)).source // \\c\\x61
new RegExp('\\c' + p).source // \\ca
\ca se interpreta como un carácter de control (código 1), mientras que \c\x61 es la secuencia \c seguida de a. En modo Unicode (u o v), tales construcciones provocan un SyntaxError, lo que simplifica la depuración.
Espacios y puntuación: Protección preventiva
La norma no explica por qué se escapan los espacios y caracteres como @. El repositorio de TC39 indica que se escapan todos los caracteres capaces de activar un "escape de contexto" en el futuro. Esto limita la entrada y salida de contexto solo a espacios o puntuación ASCII.
Este enfoque es controvertido: añade sobrecarga sin necesidad actual. La propuesta para una bandera x que ignore espacios en blanco está estancada en la etapa 1 de 4.
Comparación con funciones implementadas manualmente
Función de escape clásica de MDN (2020):
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&');
}
Cubre los metacarácteres, pero no dígitos ni letras. Una versión mejorada que escapa dígitos iniciales e hífenes:
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);
}
| Aspecto | RegExp.escape() | Personalizada (mejorada) |
|--------------------|------------------|--------------------------|
| Dígitos iniciales | \x32 | \x32 |
| Letras latinas | \x61 | No |
| Espacios/@ | \x20/\x40 | No |
| Rendimiento | Nativo | Basado en RegExp |
Recomendaciones de uso
- Para código nuevo: Usa
RegExp.escape()con un polyfill para entornos antiguos. - Modo Unicode: Siempre añade la bandera
u: detecta errores en tiempo de análisis. - ESLint: Activa la regla
@eslint/regexp/no-octal-escapeyrequire-unicode-regexp.
// Polyfill no requerido, pero útil
const polyfill = () => {
RegExp.escape = RegExp.escape || function(s) {
return s.replace(/[-[\]\/{}()\*+?\.\\^$|]/g, '\\$&');
// Extender según sea necesario
};
};
Puntos clave
- RegExp.escape() escapa dígitos/letras para concatenación de RegExp, espacios por precaución.
- Sin la bandera
u, los errores se ocultan; con ella, obtienes SyntaxError en tiempo de análisis. - Las funciones implementadas manualmente están desactualizadas: migra a la versión nativa con polyfill.
- Evita
\cX: es legado; usa códigos explícitos en su lugar. - La bandera
x(ignorar espacios en blanco) es improbable.
— Editorial Team
Aún no hay comentarios.