Они полезны, потому что функция может (почти) полностью определить значение текста внутри нее (почти = кроме заполнителей). Мне нравится использовать в качестве примера XRegExp
библиотеку Стивена Левитана. Неудобно использовать регулярные выражения, определенные как строки, потому что вам нужно дважды экранировать вещи: один раз для строкового литерала и один раз для регулярного выражения. Это одна из причин, по которой в JavaScript есть литералы регулярных выражений.
Например, предположим, что я занимаюсь обслуживанием сайта и обнаруживаю следующее:
var isSingleUnicodeWord = /^\w+$/;
... который предназначен для проверки того, содержит ли строка только «буквы». Две проблемы: A) В мире человеческого языка есть тысячи «словных» символов, которые \w
не распознает, потому что его определение ориентировано на английский язык; и B) Он включает в себя _
, что многие (включая консорциум Unicode) утверждают, что это не «буква».
Предположим, в своей работе я ввел XRegExp
в кодовую базу. Поскольку я знаю, что он поддерживает \pL
(\p
для категорий Unicode и 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>
Единственное, что я должен помнить сейчас, это то, что ${...}
особенный, потому что это заполнитель. В данном конкретном случае это не проблема, я вряд ли захочу применять квантификатор к утверждению конца ввода, но это совпадение...
person
T.J. Crowder
schedule
23.04.2017
With them you are able to modify the output of template strings using a function.
- person SPRBRN   schedule 23.07.2015