Регулярки, колбэки и… Шаблоны!

Сегодня короткий пост про простую функцию replace в мире JS. Чтобы понять нужно ли вами читать этот пост пройдите микро тест:

'abc'.replace('a', '$$$') // = ???

Смогли ответить и понимаете почему так? Значит вам не стоит читать текст далее. Для остальных — велком…

Функция replace вроде бы простая функция, ничего сложного. Правда при переходе из других языков с толку могут сбить разные нюансы использования этого метода (в JS это метод объекта String, а не функция). Хороший вопрос — на что можно заменять? Что можно подставить вторым параметром?

Многие, кто работает с JS знает, что replace вторым аргументом может принимать строки, колбэк-функции для замены и строки с плейсхолдерами, если было использовано регулярное выражение.

Плейсхолдеры регулярок похожи на то, что есть и в других языках. Но начинаются они с символа $. Например:

'start abc foo stop'.replace(/(start)(.*)(stop)/, '[$1]{ $2 }[$3]')
// [start]{ abc foo }[stop]

Таким образом мы можем легко манипулировать найденными блоками.

И все бы ничего, но в JS помимо всего прочего в методе replace есть еще поддержка шаблонов. И вот про шаблоны многие либо не знают, либо забывают. Шаблоны начинаются с символа $ и могут быть:

  • $$ — вставляет символ доллара «$»
  • $& — вставляет сопоставившуюся подстроку
  • $` — вставляет часть строки, предшествующую сопоставившейся подстроке.
  • $’ — вставляет часть строки, следующую за сопоставившейся подстрокой

И эти шаблоны могут работать как с регулярными выражениями, так и без:

'foo'.replace('foo', '$&-$&-$&') // "foo-foo-foo"
'foo'.replace(/fo{2}/, '$&-$&-$&') // "foo-foo-foo"

С помощью регулярок можно решить почти любую задачу, но иногда достаточно использовать встроенные шаблоны. Кстати, с помощью этих шаблонов можно решить часть задач, которые с помощью регулярок делаются более многословно, плюс ко всему требуют RegEx объект, в то время как шаблоны работают вне зависимости от входного параметра.

'This is a test text'.replace('test', '$`')
// result: "This is a This is a text"
// Этот шаблон эквивалентен регулярке:
'This is a test text'.replace(/(.*)test(.*)/, '$1$1$2')

Другой пример:

'This is a test text'.replace('test', "$'")
// result: "This is a text text"
// Этот шаблон эквивалентен регулярке:
'This is a test text'.replace(/(.*)test(.*)/, "$1$2$2")

Хотя регулярные выражения более гибкие, все же стоит знать про такие особенности, чтобы потом не удивляться почему при замене на $$ получается один символ $ вместо двух.

И все это есть в документации, но кто ее читает, да?