Литералы шаблонов ES6 и конкатенированные строки
У меня есть следующий код для Ecma- Script -6 template literals
let person = {name: 'John Smith'};
let tpl = `My name is ${person.name}.`;
let MyVar="My name is "+ person.name+".";
console.log("template literal= "+tpl);
console.log("my variable = "+MyVar);
Выход выглядит следующим образом:
template literal= My name is John Smith.
my variable = My name is John Smith.
это является скрипкой.
Я попытался найти точную разницу, но не смог ее найти,
Мой вопрос в том, в чем разница между этими двумя утверждениями,
let tpl = `My name is ${person.name}.`;
и
let MyVar = "My name is "+ person.name+".";
Я уже могу получить строку MyVar
, сцепленную с person.name
здесь, так что может быть сценарий для использования литерала шаблона?
Ответы
Ответ 1
Если вы используете шаблонные литералы только с заполнителями (например, 'Hello ${person.name}'
), как в примере с вопросом, то результат такой же, как просто конкатенация строк. Субъективно это выглядит лучше и легче для чтения, особенно для многострочных строк или строк, содержащих оба '
и "
поскольку вам больше не нужно экранировать эти символы.
Читаемость - отличная функция, но самое интересное в шаблонах - помеченные литералы шаблонов:
let person = {name: 'John Smith'};
let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1];
tag 'My name is ${person.name}!' // Output: My name is JOHN SMITH!
В третьей строке этого примера вызывается функция с именем tag
. Содержимое строки шаблона разделено на несколько переменных, к которым вы можете обращаться в аргументах функции tag
: литеральные разделы (в этом примере значение strArr[0]
равно My name is
а значение strArr[1]
равно !
) и замены (John Smith
). Шаблонный литерал будет оцениваться в соответствии с тем, что возвращает функция tag
.
В вики ECMAScript перечислены некоторые возможные варианты использования, такие как автоматическое экранирование или кодирование ввода или локализация. Вы можете создать функцию тега с именем msg
которая ищет буквальные части, такие как " My name is
и заменяет их переводами на текущий язык локали, например на немецкий:
console.log(msg'My name is ${person.name}.') // Output: Mein Name ist John Smith.
Значение, возвращаемое функцией tag, даже не должно быть строкой. Вы можете создать функцию тега с именем $
которая оценивает строку и использует ее как селектор запросов для возврата коллекции узлов DOM, как в этом примере:
$'a.${className}[href=~'//${domain}/']'
Ответ 2
ES6
появляется новый тип строкового литерала, используя \
back-tick` в качестве разделителя. Эти литералы позволяют встроить встроенные интерполяционные выражения, которые затем автоматически анализируются и оцениваются.
let actor = {name: 'RajiniKanth', age: 68};
let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" +
"<p>I am " + actor.age + " old</p>\n";
let newWayHtmlStr =
`<p>My name is ${actor.name},</p>
<p>I am ${actor.age} old</p>`;
console.log(oldWayStr);
console.log(newWayHtmlStr);
Как вы можете видеть, мы использовали... `` вокруг ряда символов, которые интерпретируются как строковый литерал, но любые выражения формы ${..}
анализируются и сразу вычисляются inline.
Одно действительно приятное преимущество интерполированных строковых литералов - разрешено разделять на несколько строк:
var Actor = {"name" : "RajiniKanth"};
var text =
`Now is the time for all good men like ${Actor.name}
to come to the aid of their
country!`;
console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!
Интерполированные выражения
Любое допустимое выражение разрешено появляться внутри ${..}
в интерполированной строке lit‐ eral
, включая вызовы функций, вызовы выражения встроенной функции и даже другие interpo‐ lated string literals
!
function upper(s) {
return s.toUpperCase();
}
var who = "reader"
var text =
`A very ${upper( "warm" )} welcome
to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome
// to all of you READERS!
Здесь внутренний интерполяционный строковый литерал \who\s`` был немного приятнее для нас при объединении переменной who с строкой "s"
, в отличие от who + "s". Также, чтобы сохранить примечание, интерполированный строковый литерал просто lexically scoped
, где он появляется, а не dynamically scoped
каким-либо образом
function foo(str) {
var name = "foo";
console.log( str );
}
function bar() {
var name = "bar";
foo( `Hello from ${name}!` );
}
var name = "global";
bar(); // "Hello from bar!"
Использование template literal
для HTML определенно более читаемо, уменьшая раздражение.
Простой старый способ:
'<div class="' + className + '">' +
'<p>' + content + '</p>' +
'<a href="' + link + '">Let\ go</a>'
'</div>';
С ES6
:
`<div class="${className}">
<p>${content}</p>
<a href="${link}">Let go</a>
</div>`
- Ваша строка может охватывать несколько строк.
- Вам не нужно скрывать символы котировки.
- Вы можете избежать группировок, таких как: '" > '
- Вам не нужно использовать оператор plus.
Литералы с метками шаблонов
Мы также можем пометить строку template
, когда тега template
отмечена, literals
и подстановки передаются функции, которая возвращает результирующее значение.
function myTaggedLiteral(strings) {
console.log(strings);
}
myTaggedLiteral`test`; //["test"]
function myTaggedLiteral(strings,value,value2) {
console.log(strings,value, value2);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5
Мы можем использовать оператор spread
здесь, чтобы передать несколько значений. Первый аргумент - мы называем его строками - это массив всех простых строк (материал между любыми интерполированными выражениями).
мы собираем все последующие аргументы в массив, называемый значениями с помощью ... gather/rest operator
, хотя вы, конечно, могли бы оставить их как индивидуальные именованные параметры, следуя параметру строк, как мы делали выше (value1, value2 etc)
.
function myTaggedLiteral(strings,...values) {
console.log(strings);
console.log(values);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5
argument(s)
, собранный в нашем массиве значений, является результатом уже оцененных интерполяционных выражений, найденных в строковом литерале. A tagged string literal
- это как шаг обработки после вычисления интерполяций, но до компиляции окончательного строкового значения, что позволяет вам более эффективно управлять строкой из литерала. Рассмотрим пример создания re-usable templates
.
const Actor = {
name: "RajiniKanth",
store: "Landmark"
}
const ActorTemplate = templater`<article>
<h3>${'name'} is a Actor</h3>
<p>You can find his movies at ${'store'}.</p>
</article>`;
function templater(strings, ...keys) {
return function(data) {
let temp = strings.slice();
keys.forEach((key, i) => {
temp[i] = temp[i] + data[key];
});
return temp.join('');
}
};
const myTemplate = ActorTemplate(Actor);
console.log(myTemplate);
Необработанные строки
наши функции тега получают первый аргумент, который мы назвали strings
, который является array
. Но в них добавлен еще один бит данных: необработанные необработанные версии всех строк. Вы можете получить доступ к этим исходным строковым значениям с помощью свойства .raw
, например:
function showraw(strings, ...values) {
console.log( strings );
console.log( strings.raw );
}
showraw`Hello\nWorld`;
Как вы можете видеть, версия строки raw
сохраняет сохраненную последовательность \n, в то время как обработанная версия этой строки относится к ней как к незанятой реальной новой строке. ES6
поставляется со встроенной функцией, которая может использоваться как тег строкового литерала: String.raw(..)
. Он просто проходит через исходные версии strings
:
console.log( `Hello\nWorld` );
/* "Hello
World" */
console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"
Ответ 3
Это намного чище и, как указано в комментариях, является распространенным явлением на других языках.
Другая вещь, которую я нашел приятной, - это разрывы строк, очень полезные при написании строк.
let person = {name: 'John Smith', age: 24, greeting: 'Cool!' };
let usualHtmlStr = "<p>My name is " + person.name + ",</p>\n" +
"<p>I am " + person.age + " old</p>\n" +
"<strong>\"" + person.greeting +"\" is what I usually say</strong>";
let newHtmlStr =
`<p>My name is ${person.name},</p>
<p>I am ${person.age} old</p>
<p>"${person.greeting}" is what I usually say</strong>`;
console.log(usualHtmlStr);
console.log(newHtmlStr);
Ответ 4
Хотя мой ответ не имеет прямого отношения к вопросу. Я подумал, что может быть интересным указать на один недостаток использования литералов шаблона в пользу объединения массива.
Допустим, у меня есть
let patient1 = {firstName: "John", lastName: "Smith"};
let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};
Таким образом, у некоторых пациентов есть middleName, а у других - нет.
Если бы я хотел строку, представляющую полное имя пациента
let patientName = '${patient1.firstName} ${patient1.middleName} ${patient1.lastName}';
Тогда это станет "Джон неопределенный Смит"
Однако если бы я сделал
let patientName = [patient1.firstName, patient1.middleName, patient1.lastName].join(" ");
Тогда это станет просто "Джон Смит"
РЕДАКТИРОВАТЬ
General_Twyckenham указал, что соединение "" приведет к появлению дополнительного пробела между "John" и "Smith".
Чтобы обойти это, у вас может быть фильтр перед объединением, чтобы избавиться от ложных значений: [patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");