ES6 тегированные шаблоны практическое использование
Я понимаю синтаксис шаблонов ES6 с тегами. То, что я не вижу, - это практическое использование. Когда это лучше, чем передать параметр объекта, например параметры в jQuery AJAX? $.ajax('url', { /*this guy here*/ })
Сейчас я вижу только сложный синтаксис, но я не понимаю, зачем мне это нужно/использовать. Я также обнаружил, что команда TypeScript решила реализовать ее (в 1.5) перед другими важными функциями. Какова концепция шаблонов строковых символов?
Ответы
Ответ 1
Вы можете использовать тегированные шаблоны для создания API, которые более выразительны, чем обычные вызовы функций.
Например, я работаю над доказательной концепцией библиотеки для SQL-запросов на массивах JS:
let admins = sql`SELECT name, id FROM ${users}
WHERE ${user => user.roles.indexOf('admin') >= 0}`
Обратите внимание, что это не имеет ничего общего со строковой интерполяцией; он использует маркированные шаблоны для удобства чтения. Было бы сложно построить что-то, что читается интуитивно с помощью простых вызовов функций - я думаю, у вас будет что-то вроде этого:
let admins = sql("SELECT name, id FROM $users WHERE $filter",
{ $users: users, $filter: (user) => user.roles.contains('admin') })
Этот пример - просто интересный проект, но я думаю, что он показывает некоторые преимущества отмеченных шаблонов.
Другим примером, возможно, более очевидным, является i18n - тегированный шаблон может вставить языковые версии вашего ввода.
Ответ 2
См. Описание сайта:
Заключительный этап спецификации строк шаблонов заключается в добавлении пользовательской функции перед самой строкой для создания помеченной строки шаблона.
...
Например, здесь приведен фрагмент кода для блокировки строк, которые пытаются ввести пользовательские элементы DOM:
var items = [];
items.push("banana");
items.push("tomato");
items.push("light saber");
var total = "Trying to hijack your site <BR>";
var myTagFunction = function (strings,...values) {
var output = "";
for (var index = 0; index < values.length; index++) {
var valueString = values[index].toString();
if (valueString.indexOf(">") !== -1) {
// Far more complex tests can be implemented here :)
return "String analyzed and refused!";
}
output += strings[index] + values[index];
}
output += strings[index]
return output;
}
result.innerHTML = myTagFunction `You have ${items.length} item(s) in your basket for a total of $${total}`;
Маркированные строки шаблонов могут использоваться для многих вещей, таких как безопасность, локализация, создание собственного собственного языка и т.д.
Ответ 3
Они полезны, потому что функция может (почти) полностью определять смысл текста внутри него (почти = кроме заполнителей). Мне нравится использовать пример библиотеки Стивена Левитана XRegExp
. Неловко использовать регулярные выражения, определяемые как строки, потому что вам нужно удвоить действия: однажды для строкового литерала и один раз для регулярного выражения. Это одна из причин того, что у нас есть литералы регулярного выражения в JavaScript.
Например, предположим, что я занимаюсь обслуживанием на сайте, и я нахожу это:
var isSingleUnicodeWord = /^\w+$/;
... который предназначен для проверки того, содержит ли строка только "буквы". Две проблемы: A) Есть тысячи "словесных" символов в области человеческого языка, которые \w
не распознает, потому что его определение ориентировано на английский язык; и B) Он включает _
, что многие (включая консорциум Unicode) будут утверждать, что это не "письмо".
Предположим, что в моей работе я представил XRegExp
для кодовой базы. Поскольку я знаю, что он поддерживает \pL
(\p
для категорий Юникода и L
для буквы), я мог бы быстро поменять это на:
var isSingleUnicodeWord = XRegExp("^\pL+$"); // WRONG
Тогда я задаюсь вопросом, почему это не сработало, * facepalm *, и вернитесь назад и избегайте этой обратной косой черты, поскольку она потребляется строковым литералом:
var isSingleUnicodeWord = XRegExp("^\\pL+$");
// ---------------------------------^
Вот это боль. Предположим, я мог бы написать фактическое регулярное выражение, не беспокоясь о двойном экранировании?
Я могу: с помощью отмеченной функции шаблона. Я могу поместить это в мою стандартную библиотеку:
function xrex(strings, ...values) {
const raw = strings.raw;
let result = "";
for (let i = 0; i < raw.length; ++i) {
result += raw[i];
if (i < values.length) { // 'values' always has one fewer entry
result += values[i];
}
}
return XRegExp(result);
}
Или, альтернативно, это допустимый прецедент для reduce
, и мы можем использовать деструктурирование в списке аргументов:
function xrex({raw}, ...values) {
return XRegExp(
raw.reduce(
(acc, str, index) => acc + str + (index < values.length ? values[index] : ""),
""
)
);
}
И тогда я могу с радостью написать:
const isSingleUnicodeWord = xrex'^\pL+$';
Пример:
// My tag function (defined once, then reused)
function xrex({raw}, ...values) {
const result = raw.reduce(
(acc, str, index) => acc + str + (index < values.length ? values[index] : ""),
""
);
console.log("Creating with:", result);
return XRegExp(result);
}
// Using it, with a couple of substitutions to prove to myself they work
let category = "L"; // L: Letter
let maybeEol = "$";
let isSingleUnicodeWord = xrex'^\p${category}+${maybeEol}';
function test(str) {
console.log(str + ": " + isSingleUnicodeWord.test(str));
}
test("Русский"); // true
test("日本語"); // true
test("العربية"); // true
test("foo bar"); // false
test("$£"); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/3.2.0/xregexp-all.min.js"></script>