diff options
Diffstat (limited to 'files/ru/web/javascript/reference/template_strings/index.html')
-rw-r--r-- | files/ru/web/javascript/reference/template_strings/index.html | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/files/ru/web/javascript/reference/template_strings/index.html b/files/ru/web/javascript/reference/template_strings/index.html new file mode 100644 index 0000000000..d8b4b9a442 --- /dev/null +++ b/files/ru/web/javascript/reference/template_strings/index.html @@ -0,0 +1,243 @@ +--- +title: Шаблонные строки +slug: Web/JavaScript/Reference/template_strings +tags: + - ECMAScript6 + - JavaScript + - Строки + - Шаблонные строки + - Экспериментальный +translation_of: Web/JavaScript/Reference/Template_literals +--- +<div>{{JsSidebar("More")}}</div> + +<div>Шаблонными литералами называются строковые литералы, допускающие использование выражений внутри. С ними вы можете использовать многострочные литералы и строковую интерполяцию. В спецификациях до ES2015 они назывались "шаблонными строками".</div> + +<h2 id="Syntax" name="Syntax">Синтаксис</h2> + +<pre class="syntaxbox">`строка текста` + +`строка текста 1 + строка текста 2` + +`строка текста ${выражение} строка текста` + +tag `строка текста ${выражение} строка текста` +</pre> + +<h2 id="Description" name="Description">Описание</h2> + +<p>Шаблонные литералы заключены в обратные кавычки (` `) вместо двойных или одинарных. Они могут содержать подстановки, обозначаемые знаком доллара и фигурными скобками (<code>${выражение}</code>). Выражения в подстановках и текст между ними передаются в функцию. По умолчанию функция просто объединяет все части в строку. Если перед строкой есть выражение (здесь это <code>tag</code>), то шаблонная строка называется "теговым шаблоном". В этом случае, теговое выражение (обычно функция) вызывается с обработанным шаблонным литералом, который вы можете изменить перед выводом. Для экранирования обратной кавычки в шаблонных литералах указывается обратный слэш <strong>\</strong>.</p> + +<pre class="brush: js">`\`` === '`' // --> true</pre> + +<h3 id="Многострочные_литералы">Многострочные литералы</h3> + +<p>Символы новой строки являются частью шаблонных литералов. Используя обычные строки, вставка переноса потребовала бы следующего синтаксиса:</p> + +<pre class="brush: js">console.log('string text line 1\n' + +'string text line 2'); +// "string text line 1 +// string text line 2"</pre> + +<p>То же с использованием шаблонных литералов:</p> + +<pre class="brush: js">console.log(`string text line 1 +string text line 2`); +// "string text line 1 +// string text line 2"</pre> + +<h3 id="Интерполяция_выражений">Интерполяция выражений</h3> + +<p>Для вставки выражений в обычные строки вам пришлось бы использовать следующий синтаксис:</p> + +<pre class="brush: js">var a = 5; +var b = 10; +console.log('Fifteen is ' + (a + b) + ' and not ' + (2 * a + b) + '.'); +// "Fifteen is 15 and not 20."</pre> + +<p>Теперь, при помощи шаблонных литералов, вам доступен "синтаксический сахар", делающий подстановки вроде той более читабельными:</p> + +<pre class="brush: js">var a = 5; +var b = 10; +console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); +// "Fifteen is 15 and not 20."</pre> + +<h3 id="Вложенные_шаблоны">Вложенные шаблоны</h3> + +<p>Временами, вложить шаблон — это кратчайший и, возможно, более читабельный способ составить строку. Просто поместите внутрь шаблона с обратными кавычками ещё одни, обернув их в подстановку <code>${ }</code>. Например, если выражение истинно, можно вернуть шаблонный литерал.</p> + +<p>В ES5:</p> + +<pre class="brush: js">var classes = 'header' +classes += (isLargeScreen() ? + '' : item.isCollapsed ? + ' icon-expander' : ' icon-collapser');</pre> + +<p>В ES2015 с шаблонными литералами без вложения:</p> + +<pre class="brush: js">const classes = `header ${ isLargeScreen() ? '' : + (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`; +</pre> + +<p>В ES2015 с вложенными шаблонными литералами:</p> + +<pre class="brush: js">const classes = `header ${ isLargeScreen() ? '' : +`icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`; +</pre> + +<h3 id="Теговые_шаблоны">Теговые шаблоны</h3> + +<p>Расширенной формой шаблонных литералов являются <em>теговые</em> шаблоны. Они позволяют разбирать шаблонные литералы с помощью функции. Первый аргумент такой функции содержит массив строковых значений, а остальные содержат выражения из подстановок. В итоге, функция должна вернуть собранную строку (или что-либо совсем иное, как будет показано далее). Имя функции может быть любым.</p> + +<pre class="brush: js">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</pre> + +<p>Функция тега не обязана возвращать строку, как показано в примере ниже:</p> + +<pre class="brush: js">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!" +</pre> + +<h3 id="Сырые_строки">Сырые строки</h3> + +<p>Специальное свойство <code>raw</code>, доступное для первого аргумента тегового шаблона, позволяет получить строку в том виде, в каком она была введена, без <a href="/ru/docs/Web/JavaScript/Guide/Grammar_and_types#Использование_специальных_символов_в_строках">экранирования</a>.</p> + +<pre class="brush: js">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' и два символа '\' +</pre> + +<p>Вдобавок, существует метод {{jsxref('String.raw()')}}, возвращающий точно такую же исходную строку, какую вернула бы функция шаблона по умолчанию и строковая конкатенация вместе.</p> + +<pre class="brush: js">var str = String.raw`Hi\n${2+3}!`; +// "Hi\n5!" + +str.length; +// 6 + +str.split('').join(','); +// "H,i,\,n,5,!"</pre> + +<h3 id="Теговые_шаблоны_и_экранирование_символов">Теговые шаблоны и экранирование символов</h3> + +<h4 id="Поведение_в_ES2016">Поведение в ES2016</h4> + +<p>В ECMAScript 2016 теговые шаблоны следуют правилам экранирования следующих символов:</p> + +<ul> + <li>символы Unicode, начинающиеся с "\u", например, <code>\u00A9</code></li> + <li>точки кода Unicode, начинающиеся с "\u{}", например, <code>\u{2F804}</code></li> + <li>шестнадцатеричные представления символов, начинающиеся с "\x", например, <code>\xA9</code></li> + <li>восьмеричные представления символов, начинающиеся с "\", например, <code>\251</code></li> +</ul> + +<p>Отсюда вытекает проблема теговых шаблонов: следуя грамматике ECMAScript, анализатор кода, найдя символ <code>\</code>, будет искать корректное представление символа Unicode, но может не найти его вовсе. Пример ниже показывает это:</p> + +<pre class="brush: js">latex`\unicode` +// В старых версиях ECMAScript (ES2016 и раньше) выкинет исключение: +// SyntaxError: malformed Unicode character escape sequence</pre> + +<h4 id="Поведение_в_ES2018">Поведение в ES2018</h4> + +<p>Теговые шаблоны должны позволять встраивать языки (например, <a href="https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA">DSLs</a> или <a href="https://ru.wikipedia.org/wiki/LaTeX">LaTeX</a>), в которых широко используются многие другие экранирования. Предложение <a href="https://tc39.github.io/proposal-template-literal-revision/">Редакция шаблонных литералов</a> (уровень 4, одобренный к добавлению в стандарт ECMAScript 2018) устраняет синтаксические ограничения экранирования теговых шаблонов в ECMAScript.</p> + +<p>Однако, некорректное экранирование символов по-прежнему нужно отображать в "приготовленном" отображении. Оно показывается в виде {{jsxref("undefined")}} в "приготовленном" массиве:</p> + +<pre class="brush: js">function latex(str) { + return { "cooked": str[0], "raw": str.raw[0] } +} + +latex`\unicode` + +// { cooked: undefined, raw: "\unicode" }</pre> + +<p>Заметьте, что ограничение на экранирование символов проявляется лишь в <em>теговых</em> шаблонах, и не проявляется в <em>нетеговых</em> шаблонных литералах:</p> + +<pre class="brush: js example-bad">let bad = `bad escape sequence: \unicode`;</pre> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификация</th> + <th scope="col">Статус</th> + <th scope="col">Комментарий</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-template-literals', 'Template Literals')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Изначальное определение. Определено в секциях <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-template-literals">Template Literals</a>, <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-tagged-templates">Tagged Templates</a></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-template-literals', 'Template Literals')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Определено в секциях <a href="https://tc39.github.io/ecma262/#sec-template-literals">Template Literals</a>, <a href="https://tc39.github.io/ecma262/#sec-tagged-templates">Tagged Templates</a></td> + </tr> + <tr> + <td><a href="https://tc39.github.io/proposal-template-literal-revision/">Template Literal Revision</a></td> + <td>Черновик 4-го уровня</td> + <td>Устранено ограничение экранирования в теговых шаблонах</td> + </tr> + </tbody> +</table> + +<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2> + +<div class="hidden">Таблица совместимости на этой странице сгенерирована из автоматически получаемых данных. Если вы хотите внести свои данные, пожалуйста перейдите на <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> и отправьте нам пул-реквест.</div> + +<p>{{Compat("javascript.grammar.template_literals")}}</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li>{{jsxref("String")}}</li> + <li>{{jsxref("String.raw()")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Lexical_grammar">Лексическая грамматика</a></li> + <li><a href="https://gist.github.com/WebReflection/8f227532143e63649804">Подобные шаблонам строки в ES3-совместимом синтаксисе</a></li> + <li><a href="https://hacks.mozilla.org/2015/05/es6-in-depth-template-strings-2/">ES6 в деталях: шаблонные строки</a></li> +</ul> |