Следует ли нам еще провести рефакторинг?

В самой последней версии v8 у нас теперь есть несколько новых функций JavaScript, доступных во всех основных браузерах, одна из которых - String.prototype.replaceAll. Он используется для замены всех вхождений данной строки или регулярного выражения другой строкой. Это выглядит так:

Это очень простое дополнение к String.prototype.replace. Поскольку я фанат микрооптимизации, я решил посмотреть, как эта новая функция работает по сравнению с ее альтернативами. Поэтому цель этой статьи - продемонстрировать эту новую функцию и побудить читателей подойти к новым функциям с другой точки зрения.

Каковы были альтернативы до сих пор?

Начиная с первых дней JavaScript, прототип String предоставил нам функцию с именем replace, которая, по сути, делает то же самое, что и replaceAll, но заменяет только первое вхождение searchValue. Пример:

Это полезно, но нежелательно, если вы хотите заменить все вхождения текста. Одно из решений этой проблемы - использовать RegExp для определения searchValue. Тот же пример, что и выше, можно легко переписать с помощью RegExp, чтобы добиться того же поведения, что и replaceAll:

Это хорошо работает в нашем случае. Это также очевидно для любого, кто имеет базовые знания о регулярных выражениях.

Давайте немного усложним ситуацию. Допустим, у нас есть случай, когда нам нужно, чтобы наш searchValue был динамичным. Например, предположим, что мы получили наш searchValue в качестве параметра вместо того, чтобы жестко его кодировать. В этом случае создание регулярного выражения из этой переменной становится немного сложнее. Пример:

Это работает. То, что делает код, также все еще довольно ясно. Но динамическое создание регулярного выражения не всегда просто. Специальные символы в данной строке могут легко повлиять на регулярное выражение:

Он по-прежнему работает, но теперь то, как он работает, стал намного более загадочным. Пользователи функции должны знать, что они должны очистить строку перед передачей ее функции. Другой альтернативой этому является removeFromText() дезинфекция полученного ввода. Однако в этом случае мы излишне усложняем реализацию removeFromText().

Последней альтернативой для решения описанных выше проблем является объединение .split() и .join() в цепочку для достижения того же поведения, что и replaceAll:

Теперь он охватывает все наши варианты использования. Недостатком этого является то, что то, что делает код, намного менее очевидно. Разделение строки на массив только для ее повторного слияния кажется расточительным и ничего не говорит нам о замене строки. Это больше похоже на взлом, чем на прямое выполнение того, что мы хотим делать.

По всем этим причинам у нас теперь есть синтаксический сахар replaceAll(). Я хотел бы думать, что он должен быть более производительным, чем его альтернативы, учитывая, что его ближайшая альтернатива - создание и уничтожение массива. Итак, я провел несколько тестов.

Давайте сравним производительность

Я начал с создания строки длиной 1300 символов с помощью генератора Lorem Ipsum. Затем я создал тестовые примеры нескольких способов замены всех вхождений текста в строку. Затем я использовал jsben.ch для тестирования этих тестовых примеров. Я делал это в Chrome, Safari и Firefox. Результаты представлены ниже:

Я ожидал, что replaceAll() будет немного быстрее, чем альтернативы. Вы можете себе представить, что я был весьма удивлен, увидев, что результаты кардинально меняются для каждого браузера. Однако replaceAll() не самый быстрый ни в одном из браузеров. Очень досадно видеть, что функция, которая была добавлена ​​в качестве вспомогательной, на самом деле работает медленнее, чем ее альтернативы.

Вы можете запустить те же тесты, что и я, чтобы убедиться в этом.

Вердикт

Итак, должны ли мы реорганизовать весь наш код?

Если ваш код должен быть настолько производительным, что вы выполняете микрооптимизацию своего кода, вам, вероятно, следует вместо этого использовать альтернативы. Сверхпроизводительный код часто не требуется при кодировании с помощью JavaScript, но он все равно может появиться, если вы разрабатываете служебную библиотеку или фреймворк.

Однако если вы разрабатываете приложение, ориентированное на пользователя, ваш код был бы более читабельным, если бы вы использовали более очевидные функции для достижения своей цели. Поэтому было бы лучше использовать replaceAll() и подобные помощники, чтобы сделать цель вашего кода более очевидной для читателей.

- Озан Тунча

Подпишитесь, чтобы узнать больше

Если вам понравилась эта статья и вы хотите получать уведомления о других подобных статьях, вы можете подписаться на меня здесь. Я также время от времени буду присылать вам бесплатные курсы и электронные книги. И я обещаю, что никогда не буду спамить тебя 👍