¿Cómo reemplazo todas las apariciones de una cadena en JavaScript?

Resuelto Ali asked hace 15 años • 78 respuestas

Dada una cadena:

s = "Test abc test test abc test test test abc test test abc";

Esto parece eliminar sólo la primera aparición de abcen la cadena anterior:

s = s.replace('abc', '');

¿ Cómo reemplazo todas sus apariciones?

Ali avatar Jul 18 '09 00:07 Ali
Aceptado

A partir de agosto de 2020: los navegadores modernos son compatibles con el String.replaceAll()método definido por la especificación del lenguaje ECMAScript 2021.


Para navegadores antiguos/heredados:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

Así es como evolucionó esta respuesta:

str = str.replace(/abc/g, '');

En respuesta al comentario "¿Qué pasa si 'abc' se pasa como variable?":

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

En respuesta al comentario de Click Upvote , podrías simplificarlo aún más:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(find, 'g'), replace);
}

Nota: Las expresiones regulares contienen caracteres especiales (meta) y, como tales, es peligroso pasar ciegamente un argumento en la findfunción anterior sin procesarlo previamente para escapar de esos caracteres. Esto se trata en la Guía JavaScript de Mozilla Developer Network sobre expresiones regulares , donde presentan la siguiente función de utilidad (que ha cambiado al menos dos veces desde que se escribió originalmente esta respuesta, así que asegúrese de consultar el sitio de MDN para detectar posibles actualizaciones):

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

Entonces, para que la replaceAll()función anterior sea más segura, podría modificarse a lo siguiente si también incluye escapeRegExp:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Sean Bright avatar Jul 17 '2009 17:07 Sean Bright

Para completar, me puse a pensar qué método debería usar para hacer esto. Básicamente, hay dos formas de hacer esto, como lo sugieren las otras respuestas en esta página.

Nota: En general, no se recomienda ampliar los prototipos integrados en JavaScript. Proporciono extensiones del prototipo String simplemente con fines ilustrativos, mostrando diferentes implementaciones de un método estándar hipotético en el Stringprototipo incorporado.


Implementación basada en expresiones regulares

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

Implementación de dividir y unir (funcional)

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

Sin saber demasiado sobre cómo funcionan las expresiones regulares detrás de escena en términos de eficiencia, en el pasado tendía a inclinarme hacia la implementación de división y unión sin pensar en el rendimiento. Cuando me pregunté cuál era más eficiente y por qué margen, lo usé como excusa para averiguarlo.

En mi máquina Chrome Windows 8, la implementación basada en expresiones regulares es la más rápida , mientras que la implementación de división y unión es un 53 % más lenta . Lo que significa que las expresiones regulares son dos veces más rápidas que la entrada de lorem ipsum que utilicé.

Consulte este punto de referencia que compara estas dos implementaciones entre sí.


Como se indica en el comentario a continuación de @ThomasLeduc y otros, podría haber un problema con la implementación basada en expresiones regulares si searchcontiene ciertos caracteres que están reservados como caracteres especiales en expresiones regulares . La implementación supone que la persona que llama escapará de la cadena de antemano o solo pasará cadenas que no tengan los caracteres de la tabla en Expresiones regulares (MDN).

MDN también proporciona una implementación para escapar de nuestras cadenas. Sería bueno si esto también estuviera estandarizado como RegExp.escape(str), pero lamentablemente no existe:

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

Podríamos llamar escapeRegExpdentro de nuestra String.prototype.replaceAllimplementación, sin embargo, no estoy seguro de cuánto afectará esto al rendimiento (potencialmente incluso para cadenas para las que no se necesita el escape, como todas las cadenas alfanuméricas).

Cory Gross avatar Jul 12 '2013 01:07 Cory Gross

En las últimas versiones de los navegadores más populares, puede utilizar replaceAll como se muestra aquí:

let result = "1 abc 2 abc 3".replaceAll("abc", "xyz");
// `result` is "1 xyz 2 xyz 3"

Pero primero verifique ¿ Puedo usar u otra tabla de compatibilidad para asegurarse de que los navegadores a los que se dirige tengan soporte agregado para ello primero?


Para Node.js y compatibilidad con navegadores antiguos/no actuales:

Nota: No utilice la siguiente solución en código crítico para el rendimiento.

Como alternativa a las expresiones regulares para una cadena literal simple, puede usar

str = "Test abc test test abc test...".split("abc").join("");

El patrón general es

str.split(search).join(replacement)

Esto solía ser más rápido en algunos casos que usar replaceAlluna expresión regular, pero ya no parece ser el caso en los navegadores modernos.

Punto de referencia: https://jsben.ch/TZYzj

Conclusión:

Si tiene un caso de uso crítico para el rendimiento (por ejemplo, procesar cientos de cadenas), utilice el método de expresión regular. Pero para la mayoría de los casos de uso típicos, vale la pena no tener que preocuparse por los caracteres especiales.

Matthew Crumley avatar Jul 17 '2009 20:07 Matthew Crumley