我有以下代码用于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.
this是小提琴。 我试着寻找确切的差异,但找不到它, 我的问题是这两个陈述之间有什么区别,
let tpl = `My name is ${person.name}.`;
和
let MyVar = "My name is "+ person.name+".";
我已经能够在这里获得与MyVar
连接的字符串person.name
,那么使用模板文字的场景是什么?
答案 0 :(得分:66)
如果您只在问题示例中使用了占位符(例如${expression}
)的模板文字,那么结果与仅连接字符串相同。主观上它看起来更好并且更容易阅读,特别是对于包含'
和"
的多行字符串或字符串,因为您不必再逃避这些字符。
可读性是一项很棒的功能,但有关模板的最有趣的事情是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!
在此示例的第三行中,调用名为tag
的函数。模板字符串的内容被拆分为多个变量,您可以在tag
函数的参数中访问这些变量:文字部分(在此示例中为My name is
和!
)和替换({ {1}})。模板文字将被评估为John Smith
函数返回的任何内容。 (在这种情况下)
ECMAScript wiki列出了一些可能的用例,例如自动转义或编码输入或本地化。您可以创建一个名为tag
的标记函数,该函数查找像msg
这样的文字部分,并将它们替换为当前语言环境的语言,例如德语:
My name is
标记函数返回的值甚至不必是字符串。您可以创建一个名为console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.
的标记函数,它评估字符串并将其用作查询选择器以返回DOM节点的集合,如此example:
$
答案 1 :(得分:12)
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);
正如您所看到的,我们在一系列字符周围使用了..``,这些字符被解释为字符串文字,但是${..}
形式的任何表达式都会立即进行内联解析和评估。
插值字符串文字的一个非常好的好处是允许它们分成多行:
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\'s go</a>'
'</div>';
使用ES6
:
`<div class="${className}">
<p>${content}</p>
<a href="${link}">Let's go</a>
</div>`
标记模板文字
我们还可以标记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
将所有后续参数收集到一个名为values的数组中,尽管你可以将它们作为单独的命名参数放在strings参数之后,就像我们在上面(value1, value2 etc)
所做的那样。 / p>
function myTaggedLiteral(strings,...values) {
console.log(strings);
console.log(values);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5
聚集到我们的数值数组中的argument(s)
是在字符串文字中找到的已经评估的插值表达式的结果。在计算插值之后但在编译最终字符串值之前,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);
Raw Strings
我们的标记函数会收到我们称为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"
答案 2 :(得分:4)
它更清晰,正如评论中所述,是另一种语言的常见功能。 我觉得很好的另一件事是换行符,在写字符串时非常有用。
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);
答案 3 :(得分:2)
尽管如此,我的回答并没有直接解决这个问题。我认为指出使用模板文字支持数组连接的一个缺点可能会引起一些兴趣。
我说我有
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(" ");