--- title: Шаблонные строки slug: Web/JavaScript/Reference/Template_literals tags: - ECMAScript6 - JavaScript - Строки - Шаблонные строки - Экспериментальный translation_of: Web/JavaScript/Reference/Template_literals original_slug: Web/JavaScript/Reference/template_strings ---
`строка текста` `строка текста 1 строка текста 2` `строка текста ${выражение} строка текста` tag `строка текста ${выражение} строка текста`
Шаблонные литералы заключены в обратные кавычки (` `) вместо двойных или одинарных. Они могут содержать подстановки, обозначаемые знаком доллара и фигурными скобками (${выражение}
). Выражения в подстановках и текст между ними передаются в функцию. По умолчанию функция просто объединяет все части в строку. Если перед строкой есть выражение (здесь это tag
), то шаблонная строка называется "теговым шаблоном". В этом случае, теговое выражение (обычно функция) вызывается с обработанным шаблонным литералом, который вы можете изменить перед выводом. Для экранирования обратной кавычки в шаблонных литералах указывается обратный слеш \.
`\`` === '`' // --> true
Символы новой строки являются частью шаблонных литералов. Используя обычные строки, вставка переноса потребовала бы следующего синтаксиса:
console.log('string text line 1\n' + 'string text line 2'); // "string text line 1 // string text line 2"
То же с использованием шаблонных литералов:
console.log(`string text line 1 string text line 2`); // "string text line 1 // string text line 2"
Для вставки выражений в обычные строки вам пришлось бы использовать следующий синтаксис:
var a = 5; var b = 10; console.log('Fifteen is ' + (a + b) + ' and not ' + (2 * a + b) + '.'); // "Fifteen is 15 and not 20."
Теперь, при помощи шаблонных литералов, вам доступен "синтаксический сахар", делающий подстановки вроде той более читабельными:
var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); // "Fifteen is 15 and not 20."
Временами, вложить шаблон — это кратчайший и, возможно, более читабельный способ составить строку. Просто поместите внутрь шаблона с обратными кавычками ещё одни, обернув их в подстановку ${ }
. Например, если выражение истинно, можно вернуть шаблонный литерал.
В ES5:
var classes = 'header' classes += (isLargeScreen() ? '' : item.isCollapsed ? ' icon-expander' : ' icon-collapser');
В ES2015 с шаблонными литералами без вложения:
const classes = `header ${ isLargeScreen() ? '' : (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;
В ES2015 с вложенными шаблонными литералами:
const classes = `header ${ isLargeScreen() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;
Расширенной формой шаблонных литералов являются теговые шаблоны. Они позволяют разбирать шаблонные литералы с помощью функции. Первый аргумент такой функции содержит массив строковых значений, а остальные содержат выражения из подстановок. В итоге, функция должна вернуть собранную строку (или что-либо совсем иное, как будет показано далее). Имя функции может быть любым.
var person = 'Mike'; var age = 28; function myTag(strings, personExp, ageExp) { var str0 = strings[0]; // "That " var str1 = strings[1]; // " is a " // Технически, в конце итогового выражения // (в нашем примере) есть ещё одна строка, // но она пустая (""), так что пропустим её. // var str2 = strings[2]; var ageStr; if (ageExp > 99){ ageStr = 'centenarian'; } else { ageStr = 'youngster'; } // Мы даже можем вернуть строку, построенную другим шаблонным литералом return `${str0}${personExp}${str1}${ageStr}`; } var output = myTag`That ${ person } is a ${ age }`; console.log(output); // That Mike is a youngster
Функция тега не обязана возвращать строку, как показано в примере ниже:
function template(strings, ...keys) { return (function(...values) { var dict = values[values.length - 1] || {}; var result = [strings[0]]; keys.forEach(function(key, i) { var value = Number.isInteger(key) ? values[key] : dict[key]; result.push(value, strings[i + 1]); }); return result.join(''); }); } var t1Closure = template`${0}${1}${0}!`; t1Closure('Y', 'A'); // "YAY!" var t2Closure = template`${0} ${'foo'}!`; t2Closure('Hello', {foo: 'World'}); // "Hello World!"
Специальное свойство raw
, доступное для первого аргумента тегового шаблона, позволяет получить строку в том виде, в каком она была введена, без экранирования.
function tag(strings) { return strings.raw[0]; } tag`string text line 1 \\n string text line 2`; // выводит "string text line 1 \\n string text line 2", // включая 'n' и два символа '\'
Вдобавок, существует метод {{jsxref('String.raw()')}}, возвращающий точно такую же исходную строку, какую вернула бы функция шаблона по умолчанию и строковая конкатенация вместе.
var str = String.raw`Hi\n${2+3}!`; // "Hi\n5!" str.length; // 6 str.split('').join(','); // "H,i,\,n,5,!"
В ECMAScript 2016 теговые шаблоны следуют правилам экранирования следующих символов:
\u00A9
\u{2F804}
\xA9
\251
Отсюда вытекает проблема теговых шаблонов: следуя грамматике ECMAScript, анализатор кода, найдя символ \
, будет искать корректное представление символа Unicode, но может не найти его вовсе. Пример ниже показывает это:
latex`\unicode` // В старых версиях ECMAScript (ES2016 и раньше) выкинет исключение: // SyntaxError: malformed Unicode character escape sequence
Теговые шаблоны должны позволять встраивать языки (например, DSLs или LaTeX), в которых широко используются многие другие экранирования. Предложение Редакция шаблонных литералов (уровень 4, одобренный к добавлению в стандарт ECMAScript 2018) устраняет синтаксические ограничения экранирования теговых шаблонов в ECMAScript.
Однако, некорректное экранирование символов по-прежнему нужно отображать в "приготовленном" отображении. Оно показывается в виде {{jsxref("undefined")}} в "приготовленном" массиве:
function latex(str) { return { "cooked": str[0], "raw": str.raw[0] } } latex`\unicode` // { cooked: undefined, raw: "\unicode" }
Заметьте, что ограничение на экранирование символов проявляется лишь в теговых шаблонах, и не проявляется в нетеговых шаблонных литералах:
let bad = `bad escape sequence: \unicode`;
Спецификация | Статус | Комментарий |
---|---|---|
{{SpecName('ES2015', '#sec-template-literals', 'Template Literals')}} | {{Spec2('ES2015')}} | Изначальное определение. Определено в секциях Template Literals, Tagged Templates |
{{SpecName('ESDraft', '#sec-template-literals', 'Template Literals')}} | {{Spec2('ESDraft')}} | Определено в секциях Template Literals, Tagged Templates |
Template Literal Revision | Черновик 4-го уровня | Устранено ограничение экранирования в теговых шаблонах |
{{Compat("javascript.grammar.template_literals")}}