Шаблонные строки ES6

Строки в JavaScript были исторически функционально ограничены, не хватает возможностей, которые можно встретить в таких языках, как Python или Ruby. Шаблонные строки ES6 (доступно в Chrome 41+), вносят существенные изменения. Они представляют способ определения строк с помощью domain-specific languages (DSL), добавляя улучшения:

  • Интерполяция строк
  • Встроенные выражения
  • Многострочный текст без хаков
  • Форматирование строк
  • Тегирование строк, для безопасного экранирования HTML, локализации и т.д.

Вместо того, чтобы добавлять еще одну функциональность к объекту String, шаблонные строки предлагают совершенно иной подход для решения этих проблем.

Синтакс

Шаблонные строки используют обратные апострофы(``), а не одинарные или двойные кавычки, к которым мы привыкли в обычных строках. Шаблонная строка может быть записана следующим образом:

var greeting = `Yo World!`;

Пока шаблонные строки не дают нам ничего нового, по сравнению с обычными строками. Давайте это исправим.

Подстановка строк

Одна из основных полезных особенностей это подстановка строк. Подстановка позволяет вам использовать любое допустимое выражение JavaScript (включая, например, сложение переменных) внутри литерала шаблона, результат будет выведен как часть строки.

Шаблонные строки могут содержать заполнитель для подстановки строк используя синтаксис $ {}, как показано ниже:

// Простая подстановка строк
var name = "Brendan";
console.log(`Yo, ${name}!`);
 
// => "Yo, Brendan!"

Поскольку все подстановки в шаблонных строках, это выражения JavaScript, то мы можем подставлять не только имена переменных. В примере ниже, мы используем математические выражения:

var a = 10;
var b = 10;
console.log(`JavaScript first appeared ${a+b} years ago. Crazy!`);
 
//=> JavaScript first appeared 20 years ago. Crazy!
 
console.log(`The number of JS MVC frameworks is ${2 * (a + b)} and not ${10 * (a + b)}.`);
//=> The number of JS frameworks is 40 and not 2000.

Также очень полезно использовать в подстановках функции:

function fn() { return "I am a result. Rarr"; }
console.log(`foo ${fn()} bar`);
//=> foo I am a result. Rarr bar.

${} Отлично работает с любыми типами выражений, включая вызовов методов объектов:

var user = {name: 'Caitlin Potter'};
console.log(`Thanks for getting this into V8, ${user.name.toUpperCase()}.`);
 
// => "Thanks for getting this into V8, CAITLIN POTTER";
 
// Другой пример
var thing = 'drugs';
console.log(`Say no to ${thing}. Although if you are talking to ${thing} you may already be on ${thing}.`);
 
// => Say no to drugs. Although if you are talking to drugs you may already be on drugs.

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

var greeting = `\`Yo\` World!`;
Многострочный текст

Раньше, многострочный текст в JavaScript требовал использования хаков. В текущей реализации, текст должен быть либо в одну строку, либо разделен на строки с помощью обратного слеша (‘\’) перед каждой новой строкой. Например:

var greeting = "Yo \
World";

Несмотря на то, что это хорошо работает в большинстве современных движков JavaScript, само такое поведение является небольшим хаком. Можно также использовать конкатенацию, как фейковую поддержку многострочности, но в этом мало полезного:

var greeting = "Yo " +
"World";

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

console.log(`string text line 1
string text line 2`);

Любые лишние пробелы в таком тексте, также будут являться частью строки.

Тегированные шаблоны

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

Преобразовать шаблонную строку в тегированный шаблон, можно поместив перед шаблонной строкой имя функции. Например:

fn`Hello ${you}! You are looking ${adjective} today!`

Семантика тегированных шаблонных строк очень отличается от обычных. В сущности это особый тип вызова функции. Строку выше, можно представить в виде:

fn(["Hello ", "! You are looking ", " today!"], you, adjective);

Примечание: Николас Закас более подробно рассматривает эти аргументы в разделе Template Strings его замечательной книги - Understanding ES6.

Обратите внимание, как (n + 1)-ый аргумент соответствует подстановке, которая занимает место между n-ым и (n + 1)-ым элементом массива строк. Это может быть полезно в различных ситуациях, но одной, из наиболее простых, является автоматическое экранирование интерполированных переменных.

Например, вы могли бы написать функцию для HTML экранирования, подобно этой:

html`<p title="${title}">Hello ${you}!</p>`

Которая возвращает строку с подставленными соответствующими переменными, но с замещенными HTML-небезопасными символами. Давайте сделаем это. Наша функция HTML-экранирования принимает два аргумента: имя пользователя и комментарий. Оба могут содержать HTML-небезопасные символы (‘, “, <, >, и &). Например, если имя пользователя - “Domenic Denicola” и комментарий - “& is a fan tag”, мы вернем строку:

<b>Domenic Denicola says:</b> "&amp; is a fun tag"

Наша реализация тегированного шаблона может выглядеть следующим образом:

function html(pieces) {
    var result = pieces[0];
    var substitutions = [].slice.call(arguments, 1); 
    for (var i = 0; i < substitutions.length; ++i) {
        result += escape(substitutions[i]) + pieces[i + 1];
    }
 
    return result;
}
 
function escape(s) {
    return s.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/'/g, "&#39;")
            .replace(/"/g, "&quot;");
}
 
var username = "Domenic Denicola";
var tag = "& is a fun tag";
console.log(html`<b>${username} says</b>: "${tag}"`);
//=> <b>Domenic Denicola says</b>: "&amp; is a fun tag"

Другие способы применения это автоматическое экранирование, форматирование, локализация и более сложные замены:

// авто-экраннирование
qsa`.${className}`;
safehtml`<a href="${url}?q=${query}" onclick="alert('${message}')" style="color: ${color}">${message}</a>`;
 
// локализация и форматирование
l10n`Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!`
 
// встраивание HTML/XML
jsx`<a href="${url}">${text}</a>` // becomes React.DOM.a({ href: url }, text)
 
// DSL для исполнения кода
var childProcess = sh`ps ax | grep ${pid}`;
Заключение

Шаблонные строки поддерживаются в Chrome 41 beta+, IE Tech Preview, Firefox 35+ и io.js. Практически говоря, если вы хотели бы использовать их в продакшене сегодня, они поддерживаются в мажорной версии ES6 Transpiler, в том числе Tracuer и 6to5. Воспользуйтесь нашим примером шаблонных строк из репозитория примеров Chrome, если хотите попробовать их в действии. Вас также могут заинтересовать аналоги ES6 в ES5, которые демонстрируют, как получить некоторую часть синтаксического сахара шаблонных строк используя ES5.

Шаблонные строки добавляют много важных возможностей в JavaScript. Они включают улучшенные способы работы с интерполяцией строк и выражений, многострочные тексты и возможность создавать свои собственные DSL.

Одной из наиболее важных особенностей шаблонных строк являются тегированные шаблоны - важнейшая функция для применения DSL. Они получают части шаблонной строки в качестве аргументов, и вы можете решить, как использовать строки и подстановки, чтобы определить окончательный результат вывода вашей строки.

Ссылки по теме

Оригинал на английском

Авторизация