Дима

Тэговые шаблоны в JS

В JS есть литерал шаблонной строки: «`». Большинство знает и любит его за многострочность и простую интерполяцию (передаю привет %s).

Но каким-то образом от всеобщего внимания ускользает фича, добавленная аж в 2015 году — тэговые шаблоны. Они позволяют вытащить из строки интерполированные в неё значения. Например:

function formatPrice(strings, ...prices) {
  /* Функция принимает:
  - 1 аргумент — массив строк, разбитый интерполируемыми значениями;
  - ∞ аргументов — сами значения. Я использовал деструкцию. */

  const formatter = new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: 'RUB',
    minimumFractionDigits: 0
  })

  let result = ""

  // Ключевой момент: итерируем по интерполируемым значениям
  for (const [i, price] of prices.entries()) {
    result += strings[i] + formatter.format(price)
  }
  // В конце нужно добавить последний кусочек строки — их всегда на 1 больше, чем значений.
  result += strings.at(-1)

  return result
}

formatPrice`Стоит ${5000}, но я по-братски отдам за ${3000}` 
// -> "Стоит 5 000 ₽, но я по-братски отдам за 3 000 ₽"

Тэговые шаблоны хороши, когда надо обработать вручную засунутые в строку значения. Но ведь это не очень частый случай. Да?

А вот и нет. Злодей всё это время прятался у нас под носом. Любой, кто работал с библиотеками для SQL, знает такую боль:

db.query(
  "INSERT INTO users (name, bio, age) VALUES (?, ?, ?)",
  [ name, bio, age ]
)

Даже с именновенными выражениями код будет выглядеть бесчеловечно (опять привет, %s).

Любому новичку хочется записать значения сразу прям в строку запроса, потому что это, ну, логично. Продвинутые ребята забьют его за это ногами, но втайне они сами хотят так делать. Просто это одна из ситуаций, когда беспощадный компьютер заставляет работать человека.

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

db.query`
  INSERT INTO users (name, avatar, bio)
  VALUES ${name}, ${bio}, ${age}
`

Да, вот так просто. И инъекций нет.

Я знаю лишь одну библиотеку, которая использует такую крутизну — @databases. Почему остальные продолжают сидеть на вопросиках — загадка. Время на размышление вам не ограничиваю.