Шаблоны строк

Последнее обновление: 23.08.2023

Шаблоны строк (template strings / template literals) позволяют вставлять в строку различные значения. Подобный прием еще называют интерполяцией. Для этого строки заключаются в косые кавычки, а вставляемое значение предваряется символом $ и заключается в фигурные скобки:

const name = "Tom";
const hello = `Hello ${name}`;
console.log(hello);		// Hello Tom

Здесь на место ${name} будет вставляться значение константы name. Таким образом, из шаблона `Hello ${name}` мы получим строку Hello Tom.

Подобным образом в строку можно вставлять сразу несколько значений:

const name = "Tom";
const age = 37;
const userInfo = `${name} is ${age} years old`;
console.log(userInfo);		// Tom is 37 years old

Также вместо скалярных значений могут добавляться свойства сложных объектов:

const tom ={
	name: "Tom",
	age: 22
}
const tomInfo = `${tom.name} is ${tom.age} years old`;
console.log(tomInfo);		// Tom is 22 years old

Любо можно вставлять более сложные вычисляемые выражения:

function sum(x, y){
	return x + y;
}
const a = 5;
const b = 4;

const result = `${a} + ${b} = ${sum(a, b)}`;
console.log(result);	// 5 + 4 = 9


const expression = `${a} * ${b} = ${ a * b}`;
console.log(expression);	// 5 * 4 = 20

В первом случае в шаблоне вызывается функция sum(), параметрам которой передаются значения констант a и b: ${sum(a, b)}. В итоге в это место будет вставлена сумма a и b.

Во втором случае в шаблоне выполняется операция умножения констант: ${ a * b}.

html-код в шаблонах

Шаблоны также могут хранить html-код, который будет динамически формироваться.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
	<title>METANIT.COM</title>
</head>
<body>
<script>
const tom = {name: "Tom", age: 37};
const markup = `<div>
	<p><b>Name</b>: ${tom.name}</p>
	<p><b>Age</b>: ${tom.age}</p>
</div>`;

document.body.innerHTML = markup;
</script>
</body>
</html>
String templates in JavaScript

Вложенные шаблоны

Рассмотрим другой пример - создадим из элементов массива список html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
	<title>METANIT.COM</title>
</head>
<body>
<script>
const people = [{name: "Tom", age: 37}, {name:"Sam", age: 41}, {name: "Bob", age: 21}];
const markup = `<ul>
	${people.map(person => `<li>${person.name}</li>`)}
</ul>`;

document.body.innerHTML = markup;
</script>
</body>
</html>
Шаблоны строк в JavaScript

В данном случае мы имеем дело с вложенным шаблоном. То есть вначале определяется общий внешний шаблон:

const markup = `<ul>
	${.............}
</ul>`;

А в динамически формируемом выражении применяется еще один шаблон:

${people.map(person => `<li>${person.name}</li>`)}

В данном случае у массива people вызывается функция map(), которое определяет некоторое действие для каждого элемента массива. Это действие передается в map() в виде функции. Здесь для упрощения в качестве такой функции применяется лямбда-выражение. Оно получает каждый элемент массива через параметр person и для него формирует шаблон строки `<li>${person.name}</li>`.

Тег-функции и передача шаблона строки в функцию

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

const person = "Tom";

function check (parts, name){
	console.log(parts);
	return parts[0] + name + parts[1];
}
const checkedTemplate = check`Person: ${person}.`;
console.log(checkedTemplate);

Здесь определена tag-функция check(), которая имеет два параметра: parts и name

function check (parts, name){
	console.log(parts);
	return parts[0] + name + parts[1];
}

Параметр parts - это массив частей шаблона, разделенных вставляемыми динамическими фрагментами. Второй параметр - name - это динамически вычисляемый фрагмент шаблона. То есть в данном случае мы предполагаем, что шаблон строки, который передается в функцию check(), будет иметь только один динамчески вычисляемый фрагмент. Соответственно в массиве parts будет два элемента: статическая часть шаблона, которая идет до вычисляемого фрагмента, и часть шаблона, которая идет после.

Чтобы было более ясно, о чем идет речь, в функции выводим на консоль эти элементы массива parts.

Функция возвращает return parts[0] + name + parts[1], то есть по сути мы просто возвращаем ранее сформированный шаблон, ничего не меняя.

Обратите внимание, как мы передаем этой функции шаблон:

const checkedTemplate = check`Person: ${person}.`;

шаблон просто указывается после названия функции. Или иначе говоря, tag-функция указывается как префикс перед шаблоном.

Результат работы программы:

Array(2)
	0: "Person: "
	1: "."
	length: 2
	raw: (2) ['Person: ', '.']
	[[Prototype]]: Array(0)
Person: Tom.

Из консольного вывода мы видим, что элементами массива parts являются подстроки "Person: " и ".". А в качестве значения параметра name передается строка "Tom". Стоит отметить, что даже если после динамически вычисляемого фрагмента больше не было бы никаких символов (например, `Person: ${person}`), то массив parts все равно имел бы два элемента, только вторым элементом тогда была бы пустая строка.

Но в примере выше мы просто возвращали то же содержимое, которое было сформировано на основе шаблона. Однако мы можем выполнить некоторую обработку:

const tom = "Tom";
const admin = "Admin";

function check (parts, name){
	if(name === "Admin") return "Пользователь не определен";
	else return parts[0] + name + parts[1];
}
let checkedTemplate1 = check`Пользователь: ${tom}`;
let checkedTemplate2 = check`Пользователь: ${admin}`;

console.log(checkedTemplate1);
console.log(checkedTemplate2);

В данном случае, если в шаблон передается значение "Admin", то возвращаем один результат, иначе возвращаем, то, что было бы сформированно на основе шаблона.

Пользователь: Tom
Пользователь не определен

Подобным образом можно обрабатывать шаблоны с большим количеством вычисляемых фрагментов:

const tom = {name: "Tom", age: 37};
const bob = {name: "Bob", age: 11};

function check (parts, name, age){
	if(age > 18) return `${parts[0]}${name}. Доступ открыт`;
	else return `Для пользователя ${name} доступ закрыт. Возраст ${age} недействителен`;
}
let checkedTemplate1 = check`Пользователь: ${tom.name} ${tom.age}`;
let checkedTemplate2 = check`Пользователь: ${bob.name} ${bob.age}`;

console.log(checkedTemplate1);
console.log(checkedTemplate2);

В данном случае шаблон содержит два динамческих фрагмента. Соответственно в массива part будет три элемента.

В функции check() в зависимости от значения второго динамического фрамегмента (условного возраста пользователя) возвращаем то или иное значение.

Консольный вывод:

Пользователь:  Tom. Доступ открыт
Для пользователя Bob доступ закрыт. Возраст 11 недействителен
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850