Как реализовать функцию шаблонизатора строки с подстановкой параметров в JavaScript?
Что проверяют
Знаете ли вы String.prototype.replace с функцией-заменителем и регулярные выражения, и видите ли границы задачи: отсутствующие ключи, вложенные пути, безопасность. Частый уточняющий вопрос: чем ваша функция отличается от встроенных шаблонных литералов и почему их нельзя просто взять.
Как отвечать
Сначала разведите понятия. Шаблонный литерал в обратных кавычках вычисляется сразу, в момент выполнения, и берёт переменные из текущей области видимости. Шаблонизатор нужен, когда шаблон приходит как данные: из конфига, с сервера, из словаря переводов. Поэтому шаблон это обычная строка, а значения подставляет ваша функция.
Каркас решения:
- регулярка:
/\{\{\s*([\w.]+)\s*\}\}/gдля синтаксиса{{ name }}или/\$\{(\w+)\}/gдля${name}. Фигурные скобки лучше экранировать явно: с флагомuодиночная{становится синтаксической ошибкой; - замена функцией:
template.replace(re, (match, key) => ...). Значение, которое вернула функция, вставляется как есть, а строка-заменитель интерпретировала бы$&и$1; - проверка ключа:
Object.hasOwn(params, key), а неkey in params. Иначе{{toString}}найдёт метод в прототипе и подставит текст функции; - вложенные пути:
key.split('.').reduce((obj, k) => obj?.[k], params)дляuser.name; - политика пропуска: оставить плейсхолдер, подставить пустую строку или бросить ошибку. Лучше сделать это параметром, чем зашивать
console.warn.
Если шаблоны горячие, упомяните предкомпиляцию: разобрать шаблон один раз в массив кусков и потом только склеивать.
Где спотыкаются
Проверяют функцию на строке в обратных кавычках вместо обычных. Движок подставит ${name} ещё до вызова функции или упадёт с ReferenceError, и шаблонизатору нечего будет обрабатывать.
Вставляют результат в innerHTML. Значения из пользовательских данных нужно экранировать, иначе шаблонизатор становится дырой для XSS.
Используют жадный .* вместо ленивого квантификатора или класса символов. На строке с двумя плейсхолдерами выражение \{(.*)\} захватит всё от первой скобки до последней.