【问题标题】:Usage of the backtick character (`) in JavaScriptJavaScript 中反引号 (`) 的使用
【发布时间】:2015-02-25 00:01:13
【问题描述】:

在 JavaScript 中,反引号 似乎与单引号的作用相同。例如,我可以使用反引号来定义这样的字符串:

var s = `abc`;

有没有一种方法可以使反引号的行为实际上不同于单引号的行为?


† 请注意,在程序员中,“反引号”是更普遍地称为grave accent 的名称之一。程序员有时也使用alternate names“backquote”和“backgrave”。此外,on Stack Overflow 和其他地方,“反引号”的其他常见拼写是“反引号”和“反引号”。

【问题讨论】:

标签: javascript backticks single-quotes template-strings backquote


【解决方案1】:

这是一个名为template literals的功能。

在 ECMAScript 2015 规范的早期版本中,它们被称为“模板字符串”。

Firefox 34、Chrome 41 和 Edge 12 及更高版本支持模板文字,但 Internet Explorer 不支持。

模板文字可用于表示多行字符串,并可使用“插值”插入变量:

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

【讨论】:

  • 由于缺乏对它的支持,是否有任何可行的 polyfils?
  • @AlexanderDixon,不,你不能在经典意义上对这个语言特性进行 polyfill,尽管你可以使用来自 Underscorelodash 的模板来处理字符串中的变量,并结合使用数组的多行字符串: ["a", "b"].join(""); // both string elements written in new lines。但除此之外,可能会使用像 Babel 这样的“转译器”将 ES6+ 转换为 ES5
  • Tagged template literals 使用反引号!这是有效的并且运行良好:alert`1`.
  • @UnionP 支持包括 MS Edge 在内的所有主流浏览器:kangax.github.io/compat-table/es6/#test-template_literals
  • @kiki 看起来脚本语言是 ECMAScript 的变体。 Google App 脚本显然不支持 ECMAScript 2015 功能。我无法找到他们使用什么语言的官方规范。
【解决方案2】:

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` 内插字符串文字对我们来说更方便一些。另外要注意的是,插入的字符串文字只是在其出现的地方进行词法作用域,而不是以任何方式动态作用域:

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

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

然后,我们使用... gather/rest operator 将所有后续参数收集到一个名为 values 的数组中,尽管您当然可以像我们上面所做的那样将它们作为单独的命名参数留在字符串参数之后(value1value2、等等)。

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

原始字符串

我们的标签函数接收我们称为字符串的第一个参数,它是一个数组。但是还有一点额外的数据:所有字符串的原始未处理版本。您可以使用.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"

【讨论】:

  • 很好的答案!次要评论,在您的标记模板文字部分,我相信myTaggedLiteral`test ${someText} ${2 + 3}`; 的两个示例数组输出应该是//["test ", " "](即不修剪字符串)。
  • 很好的解释和广泛的报道,谢谢。只是想补充一点,Mozilla 开发者网站Template literals (Template strings) 也有一个很好的概述,其中涵盖了一些额外的方面。
  • Nit: "ECMAScript 6 提出了一种新型的字符串文字" 这不是字符串文字,而是模板文字。如果未标记,则在评估时会产生一个字符串。这不仅仅是教条式的,在某些不允许使用模板文字的地方(例如未计算的参数名称、模块标识符...),您可以使用字符串文字。
  • 包含的句子“是一个插入的字符串文字只是词法范围” 是不可理解的。你能解决它吗?
【解决方案3】:

反引号 (`) 用于定义模板文字。模板文字是 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?

【讨论】:

    【解决方案4】:

    反引号包含模板文字,以前称为模板字符串。模板文字是允许嵌入表达式和字符串插值功能的字符串文字。

    模板文字在占位符中嵌入了表达式,用美元符号和表达式周围的花括号表示,即${expression}。占位符 / 表达式被传递给一个函数。默认函数只是连接字符串。

    要转义反引号,请在其前面加上反斜杠:

    `\`` === '`'; => true
    

    使用反引号更容易编写多行字符串:

    console.log(`string text line 1
    string text line 2`);
    

    console.log(`Fifteen is ${a + b} and
    not ${2 * a + b}.`);
    

    对比原生 JavaScript:

    console.log('string text line 1\n' +
    'string text line 2');
    

    console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
    

    转义序列:

    • \u 开始的Unicode 转义,例如\u00A9
    • \u{} 指示的Unicode 代码点转义,例如\u{2F804}
    • \x 开始的十六进制转义,例如\xA9
    • \ 和(一个)数字开头的八进制文字转义,例如\251

    【讨论】:

      【解决方案5】:

      总结:

      JavaScript 中的反引号是 ECMAScript 6 // ECMAScript 2015 中引入的一项功能,用于制作简单的动态字符串。此 ECMAScript 6 功能也称为模板字符串文字。与普通字符串相比,它具有以下优点:

      • 在模板字符串中允许换行,因此可以是多行。普通字符串文字(用''"" 声明)不允许有换行符。
      • 我们可以使用${myVariable} 语法轻松地将变量值插入到字符串中。

      示例:

      const name = 'Willem';
      const age = 26;
      
      const story = `
        My name is: ${name}
        And I'm: ${age} years old
      `;
      
      console.log(story);

      浏览器兼容性:

      所有主要浏览器供应商(Internet Explorer 除外)都原生支持模板字符串文字。因此,在您的生产代码中使用它是非常安全的。浏览器兼容性的更详细列表可以找到here

      【讨论】:

        【解决方案6】:

        好处是我们可以直接做基础数学:

        let nuts = 7
        
        more.innerHTML = `
        
        <h2>You collected ${nuts} nuts so far!
        
        <hr>
        
        Double it, get ${nuts + nuts} nuts!!
        
        `
        &lt;div id="more"&gt;&lt;/div&gt;

        它在工厂函数中变得非常有用:

        function nuts(it){
          return `
            You have ${it} nuts! <br>
            Cosinus of your nuts: ${Math.cos(it)} <br>
            Triple nuts: ${3 * it} <br>
            Your nuts encoded in BASE64:<br> ${btoa(it)}
          `
        }
        
        nut.oninput = (function(){
          out.innerHTML = nuts(nut.value)
        })
        <h3>NUTS CALCULATOR
        <input type="number" id="nut">
        
        <div id="out"></div>

        【讨论】:

        • 现在没有人轻笑cmon了吗
        【解决方案7】:

        除了字符串插值,你还可以使用反引号调用函数。

        
        var sayHello = function () {
            console.log('Hello', arguments);
        }
        
        // To call this function using ``
        
        sayHello`some args`; // Check console for the output
        
        // Or
        sayHello`
            some args
        `;
        
        

        Check styled component。他们大量使用它。

        【讨论】:

          【解决方案8】:

          这是一个非常有用的功能,例如这里是一个 Node.js 代码 sn-p 来测试 3 秒计时功能的设置。

          const waitTime = 3000;
          console.log(`setting a ${waitTime/1000} second delay`);
          

          说明

          1. 声明等待时间为 3000
          2. 使用反引号,您可以将“等待时间”除以 1000 的计算结果嵌入到所选文本的同一行中。
          3. 使用“waitTime”常量进一步调用计时器函数将导致 3 秒延迟,如 console.log 参数中所计算的那样。

          【讨论】:

            【解决方案9】:

            您也可以制作模板模板,并访问私有变量。

            var a= {e:10, gy:'sfdsad'}; //global object
            
            console.log(`e is ${a.e} and gy is ${a.gy}`); 
            //e is 10 and gy is sfdsad
            
            var b = "e is ${a.e} and gy is ${a.gy}" // template string
            console.log( `${b}` );
            //e is ${a.e} and gy is ${a.gy}
            
            console.log( eval(`\`${b}\``) ); // convert template string to template
            //e is 10 and gy is sfdsad
            
            backtick( b );   // use fonction's variable
            //e is 20 and gy is fghj
            
            function backtick( temp ) {
              var a= {e:20, gy:'fghj'}; // local object
              console.log( eval(`\`${temp}\``) );
            }
            

            【讨论】:

              【解决方案10】:

              很多 cmets 回答了你的大部分问题,但我主要想为这个问题做出贡献:

              有没有一种方法可以使反引号的行为实际上不同于单引号的行为?

              我注意到模板字符串的一个区别是无法将其设置为对象属性。更多信息this post;来自已接受答案的有趣引用:

              模板字符串是表达式,而不是文字1。

              但基本上,如果您想将其用作对象属性,则必须使用方括号括起来。

              // Throws error
              const object = {`templateString`: true};
              
              // Works
              const object = {[`templateString`]: true};
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-09-22
                • 1970-01-01
                • 2021-08-07
                • 2014-09-28
                • 1970-01-01
                • 2017-12-07
                相关资源
                最近更新 更多