Как заменить все вхождения строки в JavaScript?
Дана строка:
string = "Test abc test test abc test test test abc test test abc";
Базовый метод replace() удаляет только первое вхождение “abc” в приведенной выше строке:
string = string.replace('abc', '');
Как можно заменить ВСЕ вхождения “abc” в строке?
Чтобы заменить все вхождения строки в JavaScript, можно использовать либо современный метод replaceAll(), либо традиционный подход с replace() в сочетании с регулярным выражением, использующим глобальный флаг (/g). Метод replaceAll() является самым простым решением, в то время как подход с регулярными выражениями работает в более старых версиях браузеров.
Содержание
- Проблема с методом
replace() - Метод 1: Использование
replaceAll() - Метод 2: Использование
replace()с глобальным регулярным выражением - Метод 3: Альтернативные подходы
- Сравнение производительности
- Совместимость с браузерами
- Практические примеры
- Лучшие практики
Проблема с методом replace()
Базовый метод replace() в JavaScript заменяет только первое вхождение подстроки, как вы, возможно, заметили:
const string = "Test abc test test abc test test test abc test test abc";
const result = string.replace('abc', '');
console.log(result);
// Вывод: "Test test test abc test test test abc test test abc"
Это ограничение давно является источником путаницы для разработчиков JavaScript [источник]. Метод replace() был разработан для замены только первого совпадения при использовании строкового шаблона, если вы не укажете иное [источник].
Метод 1: Использование replaceAll()
Метод replaceAll() является современным и простым решением для замены всех вхождений подстроки [источник].
Базовое использование
const string = "Test abc test test abc test test test abc test test abc";
const result = string.replaceAll('abc', '');
console.log(result);
// Вывод: "Test test test test test test test test "
Ключевые особенности
- Глобальная замена по умолчанию: При использовании строкового шаблона
replaceAll()автоматически заменяет все вхождения [источник] - Гибкие типы шаблонов: Принимает как строки, так и регулярные выражения в качестве шаблонов
- Поддержка функций: Может принимать функцию замены для динамической замены
- Неизменяемая операция: Возвращает новую строку без изменения исходной [источник]
С регулярными выражениями
При использовании регулярных выражений с replaceAll() вы обязаны включить глобальный флаг (/g), в противном случае будет выброшена ошибка TypeError [источник]:
// Правильное использование с глобальным флагом
const result = string.replaceAll(/abc/g, '');
// Это вызовет ошибку:
// TypeError: replaceAll must be called with a global RegExp
const errorResult = string.replaceAll(/abc/, '');
Метод 2: Использование replace() с глобальным регулярным выражением
Для сред, которые не поддерживают replaceAll(), можно использовать традиционный подход с replace() и регулярным выражением с глобальным флагом [источник].
Базовое использование
const string = "Test abc test test abc test test test abc test test abc";
const result = string.replace(/abc/g, '');
console.log(result);
// Вывод: "Test test test test test test test test "
Ключевые особенности
- Универсальная совместимость: Работает во всех средах JavaScript
- Явный глобальный флаг: Четкое указание намерений с флагом
/g - Та же функциональность: Идентичные результаты с
replaceAll()при правильном использовании
Почему требуется флаг /g
Глобальный флаг (/g) указывает движку регулярных выражений находить все совпадения в строке, а не останавливаться после первого совпадения [источник]. Без него метод replace() будет вести себя точно так же, как базовый метод замены строки.
Метод 3: Альтернативные подходы
Метод разделения и соединения
Также можно добиться глобальной замены, разделив строку и соединив ее с заменой [источник]:
const string = "Test abc test test abc test test test abc test test abc";
const result = string.split('abc').join('');
console.log(result);
// Вывод: "Test test test test test test test test "
Когда использовать этот метод
- Очень простые шаблоны: Хорошо работает для простой замены подстроки
- Отсутствие сложности с регулярными выражениями: Избегает синтаксиса регулярных выражений
- Устаревшие среды: Работает в очень старых средах JavaScript
Однако этот метод обычно менее эффективен, чем подходы на основе регулярных выражений [источник].
Сравнение производительности
Результаты тестирования
Согласно различным тестам производительности [источник][источник]:
replaceAll()иreplace()с регулярными выражениями показывают незначительные различия в производительности- Метод разделения и соединения обычно медленнее в большинстве случаев использования
- Разница в производительности становится заметной только при очень больших строках (10 000+ символов)
Пример производительности
// Большая строка для тестирования производительности
const largeString = 'abc'.repeat(10000);
const startTime = performance.now();
// Тест replaceAll
const result1 = largeString.replaceAll('abc', 'xyz');
const endTime1 = performance.now();
// Тест replace с регулярным выражением
const result2 = largeString.replace(/abc/g, 'xyz');
const endTime2 = performance.now();
console.log(`replaceAll: ${endTime1 - startTime}мс`);
console.log(`regex replace: ${endTime2 - endTime1}мс`);
“Скоростная разница между ними незначительна. Вы должны обрабатывать большие строки, прежде чем даже приблизиться к разнице в скорости 0,01 миллисекунды.” [источник]
Совместимость с браузерами
Поддержка replaceAll()
Метод replaceAll() поддерживается в:
- Chrome 85+ (август 2020)
- Firefox 77+ (июнь 2020)
- Safari 13.1+ (март 2020)
- Edge 85+ (август 2020) [источник]
Полифилл для старых браузеров
Если вам нужно поддерживать старые браузеры, можно добавить полифилл [источник]:
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(pattern, replacement) {
return this.replace(new RegExp(pattern, 'g'), replacement);
};
}
Обнаружение возможностей
Всегда проверяйте доступность метода перед его использованием [источник]:
if (typeof String.prototype.replaceAll === 'function') {
// Используем replaceAll
return string.replaceAll('abc', '');
} else {
// Возвращаемся к replace с регулярным выражением
return string.replace(/abc/g, '');
}
Практические примеры
Пример 1: Простая замена текста
const text = "Быстрая коричневая лиса прыгает через ленивую собаку. Лиса была очень быстрой.";
const result = text.replaceAll('лиса', 'кошка');
console.log(result);
// Вывод: "Быстрая коричневая кошка прыгает через ленивую собаку. Кошка была очень быстрой."
Пример 2: Замена без учета регистра
const text = "ABC abc ABC abc";
const result = text.replace(/abc/gi, '');
console.log(result);
// Вывод: " "
Пример 3: Использование функции замены
const text = "а1 б2 в3 г4";
const result = text.replace(/\d/g, (match) => {
return parseInt(match) * 2;
});
console.log(result);
// Вывод: "а2 б4 в6 г8"
Пример 4: Несколько разных замен
const text = "Привет мир, привет JavaScript, привет программирование";
const result = text.replace(/привет/gi, 'Привет');
console.log(result);
// Вывод: "Привет мир, Привет JavaScript, Привет программирование"
Лучшие практики
1. Выберите правильный метод
- Используйте
replaceAll(): Для современных кодовых баз и максимальной читаемости - Используйте
replace()с регулярными выражениями: Для поддержки старых браузеров или когда нужны возможности регулярных выражений - Используйте разделение/соединение: Для очень простых случаев, когда регулярные выражения не нужны
2. Всегда тестируйте граничные случаи
// Тестируем пустые строки
const emptyResult = "abc".replaceAll('abc', ''); // Работает нормально
const emptyResult2 = "".replaceAll('abc', ''); // Также работает
// Тестируем отсутствие совпадений
const noMatch = "hello".replaceAll('abc', 'xyz'); // Возвращает исходную строку
3. Учитывайте производительность для больших строк
// Для очень больших строк учитывайте производительность
function safeReplaceAll(str, pattern, replacement) {
if (str.length > 10000) {
return str.split(pattern).join(replacement);
}
return str.replaceAll(pattern, replacement);
}
4. Документируйте свой выбор
/**
* Заменяет все вхождения подстроки в строке.
* Использует replaceAll() для современных браузеров, переходит к replace с регулярным выражением для совместимости.
*/
function globalReplace(str, search, replace) {
if (typeof String.prototype.replaceAll === 'function') {
return str.replaceAll(search, replace);
}
return str.replace(new RegExp(search, 'g'), replace);
}
Заключение
Замена всех вхождений строки в JavaScript становится простой задачей, как только вы понимаете доступные методы:
- Современный подход: Используйте
replaceAll()для чистого, читаемого кода, который автоматически обрабатывает глобальную замену - Традиционный подход: Используйте
replace()с флагом/gдля максимальной совместимости с браузерами - Простые случаи: Рассмотрите разделение/соединение для очень базальных потребностей в замене
Метод replaceAll() теперь широко поддерживается во всех основных браузерах и должен быть вашим выбором по умолчанию для новых проектов [источник]. Для устаревших кодовых баз подход с регулярными выражениями предоставляет эквивалентную функциональность с более широкой совместимостью.
Помните, что при выборе между этими методами следует учитывать требования поддержки браузеров и производительности вашей целевой аудитории, и всегда тщательно тестируйте свою реализацию.
Источники
- String.prototype.replaceAll() - JavaScript | MDN
- How do I replace all occurrences of a string? - Stack Overflow
- 3 Ways To Replace All String Occurrences in JavaScript - Dmitri Pavlutin
- How to replace all occurrences of a string in JavaScript? - CoreUI
- String.prototype.replaceAll · V8
- JavaScript replaceAll() – Replace All Instances of a String in JS - freeCodeCamp
- Benchmark: replaceAll vs regex replace - MeasureThat.net
- Replace vs Replace All Comparison - Alexander Karan