在JavaScript中,反引号†的工作原理与单引号相同。例如,我可以使用反勾号来定义这样的字符串:
var s = `abc`;
反勾号的行为与单引号的行为有区别吗?
†请注意,在程序员中,“backtick”是通常被称为严肃重音的一个名称。程序员有时也会使用“backquote”和“backgrave”这两个替代名称。此外,在Stack Overflow和其他地方,“backtick”的其他常见拼写是“back-tick”和“backtick”。
在JavaScript中,反引号†的工作原理与单引号相同。例如,我可以使用反勾号来定义这样的字符串:
var s = `abc`;
反勾号的行为与单引号的行为有区别吗?
†请注意,在程序员中,“backtick”是通常被称为严肃重音的一个名称。程序员有时也会使用“backquote”和“backgrave”这两个替代名称。此外,在Stack Overflow和其他地方,“backtick”的其他常见拼写是“back-tick”和“backtick”。
当前回答
ECMAScript 6提出了一种新的字符串文字类型,使用反勾号作为分隔符。这些字面量允许嵌入基本的字符串插值表达式,然后自动解析和求值。
let person = {name: 'RajiniKanth', age: 68, greeting: 'Thalaivaaaa!' };
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);
可以看到,我们在一系列字符周围使用了',这些字符被解释为字符串字面量,但任何形式为${..}将立即内联解析和求值。
插值字符串字面量的一个非常好的好处是它们可以被分割成多行:
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 like RajiniKanth
// to come to the aid of their
// country!
插值表达式
任何有效表达式都允许出现在${..},包括函数调用,内联函数表达式调用,甚至其他插值字符串字面量!
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 '。还要注意,插值字符串文字只是在它出现的地方进行词法作用域,而不是以任何方式进行动态作用域:
(例如:一个name变量被内插在定义template-literal的作用域中的值;在foo函数的作用域中赋值将没有效果)
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使用模板文字肯定更易于阅读,因为它减少了麻烦。
简单的老办法:
'<div class="' + className + '">' +
'<p>' + content + '</p>' +
'<a href="' + link + '">Let\'s go</a>'
'</div>';
使用ECMAScript 6:
`<div class="${className}">
<p>${content}</p>
<a href="${link}">Let's go</a>
</div>`
字符串可以跨越多行。 你不必转义引号字符。 你可以避免这样的分组:'">' 你不需要使用加号运算符。
带标签的模板文字
我们也可以标记模板字符串,当模板字符串被标记时,字面量和替换被传递给函数,该函数返回结果值。
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
我们可以在这里使用展开运算符来传递多个值。第一个参数——我们称之为字符串——是所有普通字符串(任何插值表达式之间的东西)的数组。
然后,使用…将所有后续参数收集到一个名为values的数组中。虽然您当然可以像上面所做的那样,将它们作为单独的命名参数留在字符串参数后面(value1, value2,等等)。
function myTaggedLiteral(strings, ...values) {
console.log(strings);
console.log(values);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5
收集到values数组中的参数是在字符串字面量中已经求值的插值表达式的结果。带标记的字符串字面值类似于插值计算之后,但在编译最终字符串值之前的处理步骤,允许您更好地控制从字面值生成字符串。让我们看一个创建可重用模板的例子。
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,它是一个数组。但是还包含一个额外的数据:所有字符串的原始未处理版本。你可以使用.raw属性访问这些原始字符串值,就像这样:
function showraw(strings, ...values) {
console.log(strings);
console.log(strings.raw);
}
showraw`Hello\nWorld`;
如您所见,字符串的原始版本保留了转义\n序列,而经过处理的字符串版本将其视为未转义的真正新行。ECMAScript 6提供了一个内置函数,可以用作字符串文字标记:string .raw(..)。它只是传递字符串的原始版本:
console.log(`Hello\nWorld`);
/* "Hello
World" */
console.log(String.raw`Hello\nWorld`);
// "Hello\nWorld"
其他回答
这是一个称为模板字面量的特性。
在ECMAScript 2015规范的早期版本中,它们被称为“模板字符串”。
Firefox 34、Chrome 41和Edge 12及以上版本支持模板文字,但Internet Explorer不支持。
示例:http://tc39wiki.calculist.org/es6/template-strings/ 官方规范:ECMAScript 2015语言规范,12.2.9模板文字词汇组件(有点干)
模板字面量可以用来表示多行字符串,并可以使用“插值”来插入变量:
var a = 123, str = `---
a is: ${a}
---`;
console.log(str);
输出:
---
a is: 123
---
更重要的是,它们不仅可以包含变量名,还可以包含任何JavaScript表达式:
var a = 3, b = 3.1415;
console.log(`PI is nearly ${Math.max(a, b)}`);
反勾号包含模板字面值,以前称为模板字符串。模板字面量是允许嵌入表达式和字符串插值特性的字符串字面量。
模板字面量将表达式嵌入到占位符中,由$符号和表达式周围的花括号表示,即${expression}。占位符/表达式被传递给函数。默认函数只是连接字符串。
要转义反斜杠,在它前面加一个反斜杠:
`\`` === '`'; => true
使用反勾号更容易地编写多行字符串:
console.log(`string text line 1
string text line 2`);
or
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
vs.普通JavaScript:
console.log('string text line 1\n' +
'string text line 2');
or
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
转义序列:
Unicode转义由\u开始,例如\u00A9 由\u{}表示的Unicode码位转义,例如\u{2F804} 以\x开头的十六进制转义,例如\xA9 八进制文字转义由\和(a)数字(s)开始,例如\251
ECMAScript 6提出了一种新的字符串文字类型,使用反勾号作为分隔符。这些字面量允许嵌入基本的字符串插值表达式,然后自动解析和求值。
let person = {name: 'RajiniKanth', age: 68, greeting: 'Thalaivaaaa!' };
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);
可以看到,我们在一系列字符周围使用了',这些字符被解释为字符串字面量,但任何形式为${..}将立即内联解析和求值。
插值字符串字面量的一个非常好的好处是它们可以被分割成多行:
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 like RajiniKanth
// to come to the aid of their
// country!
插值表达式
任何有效表达式都允许出现在${..},包括函数调用,内联函数表达式调用,甚至其他插值字符串字面量!
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 '。还要注意,插值字符串文字只是在它出现的地方进行词法作用域,而不是以任何方式进行动态作用域:
(例如:一个name变量被内插在定义template-literal的作用域中的值;在foo函数的作用域中赋值将没有效果)
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使用模板文字肯定更易于阅读,因为它减少了麻烦。
简单的老办法:
'<div class="' + className + '">' +
'<p>' + content + '</p>' +
'<a href="' + link + '">Let\'s go</a>'
'</div>';
使用ECMAScript 6:
`<div class="${className}">
<p>${content}</p>
<a href="${link}">Let's go</a>
</div>`
字符串可以跨越多行。 你不必转义引号字符。 你可以避免这样的分组:'">' 你不需要使用加号运算符。
带标签的模板文字
我们也可以标记模板字符串,当模板字符串被标记时,字面量和替换被传递给函数,该函数返回结果值。
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
我们可以在这里使用展开运算符来传递多个值。第一个参数——我们称之为字符串——是所有普通字符串(任何插值表达式之间的东西)的数组。
然后,使用…将所有后续参数收集到一个名为values的数组中。虽然您当然可以像上面所做的那样,将它们作为单独的命名参数留在字符串参数后面(value1, value2,等等)。
function myTaggedLiteral(strings, ...values) {
console.log(strings);
console.log(values);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5
收集到values数组中的参数是在字符串字面量中已经求值的插值表达式的结果。带标记的字符串字面值类似于插值计算之后,但在编译最终字符串值之前的处理步骤,允许您更好地控制从字面值生成字符串。让我们看一个创建可重用模板的例子。
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,它是一个数组。但是还包含一个额外的数据:所有字符串的原始未处理版本。你可以使用.raw属性访问这些原始字符串值,就像这样:
function showraw(strings, ...values) {
console.log(strings);
console.log(strings.raw);
}
showraw`Hello\nWorld`;
如您所见,字符串的原始版本保留了转义\n序列,而经过处理的字符串版本将其视为未转义的真正新行。ECMAScript 6提供了一个内置函数,可以用作字符串文字标记:string .raw(..)。它只是传递字符串的原始版本:
console.log(`Hello\nWorld`);
/* "Hello
World" */
console.log(String.raw`Hello\nWorld`);
// "Hello\nWorld"
很多评论回答了你的大部分问题,但我主要想回答这个问题:
反勾号的行为与单引号的行为有区别吗?
我注意到模板字符串的一个不同之处是不能将其设置为对象属性。更多信息在这篇文章;从公认的答案中引用一段有趣的话:
模板字符串是表达式,不是字面量1。
但基本上,如果你想把它用作对象属性你就必须用方括号把它括起来。
// Throws error
const object = {`templateString`: true};
// Works
const object = {[`templateString`]: true};
反撇号(')用于定义模板字面量。模板字面量是ECMAScript 6中的一个新特性,它使处理字符串更加容易。
特点:
我们可以在模板文字中插入任何类型的表达式。 它们可以是多线的。
注意:我们可以很容易地在反撇号(')内使用单引号(')和双引号(")。
例子:
var nameStr = `I'm "Alpha" Beta`;
为了插入变量或表达式,我们可以使用${expression}符号。
var name = 'Alpha Beta';
var text = `My name is ${name}`;
console.log(text); // My name is Alpha Beta
多行字符串意味着您不再需要在新行中使用\n。
例子:
const name = 'Alpha';
console.log(`Hello ${name}!
How are you?`);
输出:
Hello Alpha!
How are you?