Как заменить все вхождения подстроки в строке JavaScript?
Проблема: почему replace() заменяет только первое совпадение?
Метод String.prototype.replace() по умолчанию заменяет только первое найденное совпадение. Это его стандартное поведение, если не использовать регулярное выражение с флагом g (global).
В вашем примере:
text.replace("Кошка", "Собака")
— строка "Кошка" интерпретируется как литерал, и замена происходит только для первого вхождения.
Решение 1: Использование replace() с регулярным выражением (рекомендуется)
Самый правильный и гибкий способ — использовать регулярное выражение с флагом g (global) для замены всех вхождений. Флаг i (ignore case) позволяет игнорировать регистр.
Пример 1: замена всех вхождений с учётом регистра
let text = "Кошка гуляет по крыше. Кошка любит молоко. Кошка спит на диване.";
let newText = text.replace(/Кошка/g, "Собака");
console.log(newText);
// "Собака гуляет по крыше. Собака любит молоко. Собака спит на диване."
Пример 2: замена всех вхождений без учёта регистра
let text = "Кошка гуляет. кошка спит. КОШКА ест.";
let newText = text.replace(/кошка/gi, "Собака");
console.log(newText);
// "Собака гуляет. Собака спит. Собака ест."
Флаги:
g— global, заменяет все совпадения, а не только первое.i— ignore case, игнорирует регистр символов.
Решение 2: Использование replaceAll() (современный способ, ES2021+)
Начиная с ES2021, в JavaScript появился метод String.prototype.replaceAll(). Он заменяет все вхождения без необходимости использовать регулярные выражения.
Пример 3: replaceAll() с учётом регистра
let text = "Кошка гуляет по крыше. Кошка любит молоко. Кошка спит на диване.";
let newText = text.replaceAll("Кошка", "Собака");
console.log(newText);
// "Собака гуляет по крыше. Собака любит молоко. Собака спит на диване."
Важно: replaceAll() не поддерживает флаг i. Для замены без учёта регистра всё равно нужно использовать регулярное выражение с replace() или replaceAll() с предварительным приведением строки к одному регистру.
Решение 3: Замена без учёта регистра с помощью replaceAll() и toLowerCase()
let text = "Кошка гуляет. кошка спит. КОШКА ест.";
let search = "кошка";
let replacement = "Собака";
// Приводим исходный текст и искомое слово к нижнему регистру,
// но сохраняем оригинал для замены.
let lowerText = text.toLowerCase();
let lowerSearch = search.toLowerCase();
let result = "";
// Разделяем по искомому слову (в нижнем регистре) и склеиваем с заменой
let parts = lowerText.split(lowerSearch);
result = parts.join(replacement);
console.log(result);
// "Собака гуляет. Собака спит. Собака ест."
Сравнение методов
- replace() + регулярное выражение — самый гибкий вариант, работает во всех средах. Подходит для сложных шаблонов.
- replaceAll() — проще читается, но не поддерживает флаги
iиg(он и так глобальный). Подходит для простых замен без учёта регистра. - split() + join() — старый трюк, работает без регулярных выражений, но менее производителен на больших строках.
Рекомендую освоить регулярные выражения — они значительно расширяют ваши возможности при работе со строками в JavaScript.
<<Альтернативный подход: использование split() и join()
Если вы пока не хотите разбираться с регулярными выражениями, есть простой «трюк»: разбить строку на массив по искомой подстроке, а затем склеить обратно с нужной заменой.
let text = "Кошка гуляет по крыше. Кошка любит молоко. Кошка спит на диване.";
let newText = text.split("Кошка").join("Собака");
console.log(newText);
// "Собака гуляет по крыше. Собака любит молоко. Собака спит на диване."
Как это работает:
split("Кошка")— разбивает строку на массив частей, удаляя все вхождения "Кошка"..join("Собака")— склеивает все элементы массива обратно в строку, вставляя между ними "Собака".
Недостатки:
- Нельзя просто добавить игнорирование регистра (придётся дополнительно преобразовывать строку).
- Менее производительно на очень длинных строках (создаётся промежуточный массив).
- Не подходит для сложных шаблонов (например, замена всех цифр на звёздочки).
Тем не менее, для простых случаев и для начинающих это вполне рабочий вариант, который легко запомнить и использовать.
Ответов пока нет.
Войдите чтобы оставить ответ