ES6 模板文本与串联字符串

我有以下用于 ECMAScript 6 模板文本的代码:

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+".";

我已经能够将字符串与此处连接起来,那么在什么情况下使用模板文本?MyVarperson.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!

在此示例的第三行中,调用名为 的函数。模板字符串的内容被拆分为多个变量,您可以在函数的参数中访问这些变量:文本部分(在此示例中,is 的值和 is 的值)和替换 ()。模板文本将被计算为函数返回的任何内容。tagtagstrArr[0]My name is strArr[1]!John Smithtag

ECMAScript wiki 列出了一些可能的用例,例如自动转义或编码输入,或本地化。您可以创建一个名为的标记函数,该函数查找文本部分,并将其替换为当前区域设置的语言(例如德语)的翻译:msgMy name is

console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.

tag 函数返回的值甚至不必是字符串。您可以创建一个名为的标记函数,该函数计算字符串并将其用作查询选择器以返回 DOM 节点的集合,如以下示例所示:$

$`a.${className}[href=~'//${domain}/']`

答案 2

ES6 提出了一种新型的字符串文本,使用回勾作为分隔符。这些文本允许嵌入基本的字符串插值表达式,然后自动分析和计算这些表达式。`

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);

如您所见,我们使用了 ..“”围绕一系列字符,这些字符被解释为字符串文本,但该形式的任何表达式都会立即以内联方式进行解析和计算。${..}

插值字符串文本的一个非常好的好处是允许它们跨多行拆分:

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‐ eralinterpo‐ 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 变量与字符串组合时,对我们来说是一个更好的方便,而不是 who + “s”。此外,为了保持注释,内插字符串文本只是它出现的位置,而不是以任何方式:"s"lexically scopeddynamically 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!"

通过减少烦恼,将 用于 HTML 绝对更具可读性。template literal

简单的旧方法:

'<div class="' + className + '">' +
  '<p>' + content + '</p>' +
  '<a href="' + link + '">Let\'s go</a>'
'</div>';

使用 ES6:

`<div class="${className}">
  <p>${content}</p>
  <a href="${link}">Let's go</a>
</div>`
  • 字符串可以跨多行。
  • 您不必转义引号字符。
  • 您可以避免使用类似“>”的分组
  • 您不必使用加号运算符。

标记的模板文本

我们还可以标记字符串,当字符串被标记时,和 替换被传递给函数,该函数返回结果值。templatetemplateliterals

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]

收集到我们的值数组中是在字符串文本中找到的已计算插值表达式的结果。A 类似于在计算插值之后但在编译最终字符串值之前执行的处理步骤,这样可以更好地控制从文本生成字符串。让我们看一个创建 .argument(s)tagged string literalre-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);

原始字符串

我们的标签函数接收我们调用的第一个参数,它是一个 .但还有一个额外的数据位:所有字符串的原始未处理版本。您可以使用该属性访问这些原始字符串值,如下所示:stringsarray.raw

function showraw(strings, ...values) {
  console.log( strings );
  console.log( strings.raw );
}
showraw`Hello\nWorld`;

如您所见,字符串的版本保留转义的 \n 序列,而字符串的处理版本将其视为未转义的真正 new 行。ES6 附带了一个内置函数,可用作字符串文字标记:。它只是通过的原始版本:rawString.raw(..)strings

console.log( `Hello\nWorld` );
/* "Hello
World" */

console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"