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>