Javascript ES6 模板文字与连接字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27565056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:20:02  来源:igfitidea点击:

ES6 Template Literals Vs concatenated strings

javascriptnode.jsecmascript-6template-strings

提问by Naeem Shaikh

I have the following code for Ecma-Script-6 template literals

我有以下 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);

The output is as follows:

输出如下:

template literal= My name is John Smith.
my variable = My name is John Smith.

thisis the fiddle. I tried searching for the exact difference but couldn't find it, My question is what is the difference between these two statements,

是小提琴。我试图寻找确切的区别,但找不到,我的问题是这两个陈述之间的区别是什么,

  let tpl = `My name is ${person.name}.`;    

And

  let MyVar = "My name is "+ person.name+".";

I am already able to get the string MyVarconcatenated with person.namehere, so what would be the scenario to use the template literal ?

我已经能够将字符串MyVarperson.name此处连接起来,那么使用模板文字的场景是什么?

回答by kapex

If you are using template literals only with placeholders (e.g. `Hello ${person.name}`) like in the question's example, then the result is the same as just concatenating strings. Subjectively it looks better and is easier to read, especially for multi-line strings or strings containing both 'and "since you don't have to escape those characters any more.

如果您`Hello ${person.name}`在问题示例中仅使用带有占位符(例如)的模板文字,则结果与仅连接字符串相同。主观上它看起来更好并且更容易阅读,特别是对于多行字符串或包含两者的字符串'"因为您不必再​​转义这些字符。

Readability is a great feature, but the most interesting thing about templates are Tagged template literals:

可读性是一个很棒的特性,但关于模板最有趣的事情是标记模板文字

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!

In the third line of this example, a function named tagis called. The content of the template string is split into multiple variables, that you can access in the arguments of the tagfunction: literal sections (in this example the value of strArr[0]is My name isand the value of strArr[1]is !) and substitutions (John Smith). The template literal will be evaluated to whatever the tagfunction returns.

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

The ECMAScript wikilists some possible use cases, like automatically escaping or encoding input, or localization. You could create a tag function named msgthat looks up the literal parts like My name isand substitutes them with translations into the current locale's language, for example into German:

ECMAScript的维基列出了一些可能的使用情况下,如自动转义或编码输入,或定位。您可以创建一个名为的标记函数msg,用于查找文字部分My name is,并将它们替换为当前区域设置的语言的翻译,例如德语:

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

The value returned by the tag function doesn't even have to be a string. You could create a tag function named $which evaluates the string and uses it as a query selector to return a collection of DOM nodes, like in this example:

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

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

回答by Thalaivar

ES6comes up with a new type of string literal, using the \back-tick` as the delimiter. These literals do allow basic string interpolation expressions to be embedded, which are then automatically parsed and evaluated.

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

As you can see, we used the ..`` around a series of characters, which are interpreted as a string literal, but any expressions of the form ${..}are parsed and evaluated inline immediately.

如您所见,我们在一系列字符周围使用了 ..`` ,这些字符被解释为字符串文字,但该形式的任何表达式都会${..}立即内联解析和评估。

One really nice benefit of interpolated string literals is they are allowed to split across multiple lines:

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

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!

Interpolated Expressions

内插表达式

Any valid expression is allowed to appear inside ${..}in an interpolated string lit‐ eral, including function calls, inline function expression calls, and even other interpo‐ lated string literals!

任何有效的表达式都可以出现在内${..}插字符串中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!

Here, the inner \${who}s`` interpolated string literal was a little bit nicer convenience for us when combining the who variable with the "s"string, as opposed to who + "s". Also to keep an note is an interpolated string literal is just lexically scopedwhere it appears, not dynamically scopedin any way

在这里,与"s"who + "s" 相比,当将 who 变量与字符串组合时,内部的 \${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!"

Using the template literalfor the HTML is definitely more readable by reducing the annoyance.

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

The plain old way:

简单的老方法:

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

With ES6:

ES6

`<div class="${className}">
  <p>${content}</p>
  <a href="${link}">Let's go</a>
</div>`
  • Your string can span multiple lines.
  • You don't have to escape quotation characters.
  • You can avoid groupings like: '">'
  • You don't have to use the plus operator.
  • 您的字符串可以跨越多行。
  • 您不必转义引号字符。
  • 您可以避免分组,如:“>”
  • 您不必使用加号运算符。

Tagged Template Literals

标记模板文字

We can also tag a templatestring, when a templatestring is tagged, the literalsand substitutions are passed to function which returns the resulting value.

我们也可以标记一个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

We can use the spreadoperator here to pass multiple values. The first argument — we called it strings — is an array of all the plain strings (the stuff between any interpolated expressions).

我们可以在spread这里使用运算符来传递多个值。第一个参数——我们称之为字符串——是一个包含所有普通字符串(任何内插表达式之间的内容)的数组。

we then gather up all subsequent arguments into an array called values using the ... gather/rest operator, though you could of course have left them as individual named parameters following the strings parameter like we did above (value1, value2 etc).

然后,我们使用 将所有后续参数收集到一个名为 values 的数组中... 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

The argument(s)gathered into our values array are the results of the already evaluated interpolation expressions found in the string literal. A tagged string literalis like a processing step after the interpolations are evaluated but before the final string value is compiled, allowing you more control over generating the string from the literal. Let's look at an example of creating a re-usable templates.

argument(s)收集到我们的价值观数组是在字符串字面发现已经评价插值表达式的结果。Atagged 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);

Raw Strings

原始字符串

our tag functions receive a first argument we called strings, which is an array. But there's an additional bit of data included: the raw unprocessed versions of all the strings. You can access those raw string values using the .rawproperty, like this:

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

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

As you can see, the rawversion of the string preserves the escaped \n sequence, while the processed version of the string treats it like an unescaped real new-line. ES6comes with a built-in function that can be used as a string literal tag: String.raw(..). It simply passes through the raw versions of the strings:

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

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

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

回答by Rigotti

It's a lot cleaner and as stated in the comments, is a common features in another languages. The other thing that I found nice was the line breaks, very useful when writing strings.

正如评论中所述,它更清晰,是其他语言的共同特征。我发现的另一件事是换行符,在编写字符串时非常有用。

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

回答by Dhruv Prakash

While, my answer does not directly address the question. I thought it may be of some interest to point out one drawback of using template literals in favor of array join.

虽然,我的回答并没有直接解决这个问题。我认为指出使用模板文字代替数组连接的一个缺点可能会引起一些兴趣。

Lets say I have

可以说我有

let patient1 = {firstName: "John", lastName: "Smith"};
let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};

So some patients have a middleName and others do not.

所以有些患者有一个中间名,而另一些则没有。

If I wanted a string representing the full name of a patient

如果我想要一个代表患者全名的字符串

let patientName = `${patient1.firstName} ${patient1.middleName} ${patient1.lastName}`;

Then this would become "John undefined Smith"

然后这将成为“John undefined Smith”

However if I did

但是,如果我这样做了

let patientName = [patient1.firstName, patient1.middleName,  patient1.lastName].join(" ");

Then this would become just "John Smith"

然后这将变成只是“约翰史密斯”

EDIT

编辑

General_Twyckenham pointed out that a join on " " would result in an extra space between "John" and "Smith".

General_Twyckenham 指出“”上的连接会导致“John”和“Smith”之间出现额外的空格。

To get around this you can have a filter before the join to get rid of falsy values: [patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");

为了解决这个问题,您可以在加入之前使用过滤器来消除虚假值: [patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");