Template literals (Template strings)

You’re reading the English version of this content since no translation exists yet for this locale. Help us translate this article!

Mẫu nguyên thủy là chuỗi string nguyên thủy cho phép áp dụng vào các biểu thức. Bạn có thể sử dụng các chuỗi nhiều dòng và các chuỗi chức năng nội suy với chúng. Chúng được gọi là "chuỗi mẫu" trong các phiên bản trước của đặc tả ES2015.

Cú pháp

`string text`

`string text line 1
 string text line 2`

`string text ${expression} string text`

tag `string text ${expression} string text`

Mô tả

Mẫu nguyên thủy được đóng bởi dấu 'nháy-ngược' (` `)  (grave accent - nằm ở góc trái dưới phím Esc) thay vì sử dụng nháy đơn hoặc nháy kép. Mẫunguyên thủy có thể bao gồm placeholders (trong thẻ input có 1 thuộc tính placeholder). Chúng được biểu thị bằng ký hiệu đô la và dấu ngoặc nhọn (${expression}). Các biểu thức trong placeholders và văn bản giữa các dấu 'nháy-ngược' (` `) được đưa vào hàm. Hàm mặc định chỉ ghép các thành phần thành một chuỗi đơn. Nếu có một biểu thức thực hiện trước một mẫu nguyên thủy (tag - ở đây gọi là thẻ), thì được gọi là một "tagged template" (mẫu được gắn thẻ). Trong trường hợp này, biểu thức gắn thẻ (thường là một hàm) được gọi cùng với mẫu nguyên thủy, biểu thức mà sau đó bạn có thể thao tác trước khi trả ra kết quả. Để thoát dấu 'nháy-ngược' trong một mẫu nguyên thủy, hãy đặt dấu gạch chéo ngược \ trước dấu nháyngược (phần này nên note lại và cần tham khảo thêm các ví dụ sau).

`\`` === '`' // --> true

Các chuỗi nhiều dòng (chuỗi đa dòng)

Bất kỳ các dòng ký tự mới được chèn vào trong nguồn (mã nguồn) đều là một phần của mẫu nguyên thủy. Việc sử dụng các chuỗi mặc định, bạn sẽ phải sử dụng các cú pháp dưới đây để có được các chuỗi đa dòng (sử dụng ký tự \n):

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

Để có được kết quả tượng tự thì sử dụng cú pháp mẫu nguyên thủy, bạn có thể viết như sau:

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

Biểu thức nội suy

Để nhúng các thiểu thức (hàm, phép tính, ...) vào trong chuỗi mặc định, bạn sẽ sử dụng cú pháp dưới đây:

var a = 5;
var b = 10;
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
// "Fifteen is 15 and
// not 20."

Giờ đây, với các mẫu nguyên thủy, bạn có thể sử dụng các thay thế cú pháp như thế này để dễ đọc hơn:

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."

Các mẫu lồng nhau (mẫu nằm trong mẫu khác)

Trong một số trường hợp nhất định, lồng một mẫu là cách dễ nhất và có thể dễ đọc hơn để có các chuỗi có khả năng cấu hình. Bên trong một mẫu được tạo, nó đơn giản để cho phép các dấu nháy ngược bên trong chỉ đơn giản bằng cách sử dụng chúng trong một placeholder ${ } bên trong mẫu. Ví dụ, nếu điều kiện đúng: thì trả về mẫu nguyên thủy.

Trong ES5:

var classes = 'header'
classes += (isLargeScreen() ?
   '' : item.isCollapsed ?
     ' icon-expander' : ' icon-collapser');

Trong ES2015 với mẫu nguyên thủy và không đặt lồng nhau:

const classes = `header ${ isLargeScreen() ? '' :
    (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;

Trong ES2015 với 2 mẫu nguyên thủy đặt lồng nhau:

const classes = `header ${ isLargeScreen() ? '' :
 `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;

Các mẫu được gắn thẻ

Một hình thức nâng cao hơn của mẫu nguyên thủy là các mẫu được gắn thẻ. Các thẻ cho phép bạn chuyển đổi các mẫu nguyên thủy sử dụng hàm. Tham số đầu tiên của hàm gắn thẻ bao gồm một mảng các chuỗi. Các tham số còn lại được gắn với các biểu thức. Cuối cùng, hàm của bạn có thể trả về chuỗi được thao tác (hoặc nó có thể trả về bất kỳ kết quả gì theo mục đích lập trình trong ví dụ tiếp theo).  Tê của hàm được sử dụng cho thẻ bạn có thể đặt tên theo cách bạn muốn.

var person = 'Mike';
var age = 28;

function myTag(strings, personExp, ageExp) {
  var str0 = strings[0]; // "That "
  var str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // var str2 = strings[2];

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  // We can even return a string built using a template literal
  return `${str0}${personExp}${str1}${ageStr}`;
}

var output = myTag`That ${ person } is a ${ age }`;

console.log(output);
// That Mike is a youngster

Các hàm gắn thẻ không cần trả về một chuỗi, như được hiển thị ở ví dụ dưới đây.

function template(strings, ...keys) {
  return (function(...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function(key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join('');
  });
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure('Y', 'A');  // "YAY!"
var t2Closure = template`${0} ${'foo'}!`;
t2Closure('Hello', {foo: 'World'});  // "Hello World!"

Các chuỗi chưa xử lý (chuỗi thô)

thuộc tính raw khá đặc biệt, có thể trong tham số đầu tiên để gán thẻ hàm, nó cho phép bạn truy cập các chuỗi thô như khi chúng được đưa vào, không cần sử lý escape sequences.

function tag(strings) {
  console.log(strings.raw[0]);
}

tag`string text line 1 \n string text line 2`;
// logs "string text line 1 \n string text line 2" ,
// including the two characters '\' and 'n'

Ngoài ra, phương thức String.raw() tồn tại để tạo các chuỗi thô giống như hàm mẫu mặc định và chuỗi nối.

var str = String.raw`Hi\n${2+3}!`;
// "Hi\n5!"

str.length;
// 6

str.split('').join(',');
// "H,i,\,n,5,!"

Mẫu được gắn thẻ và trình tự thoát

ES2016 behavior

Trong ECMAScript 2016, các mẫu được gắn thẻ tuân theo quy tắc của các trình tự thoát sau đây:

  • Unicode escapes bắt đầu bởi  "\u", ví dụ \u00A9
  • Unicode code point escapes chỉ định bởi "\u{}", ví dụ \u{2F804}
  • Hexadecimal escapes bắt đầu bởi "\x", ví dụ \xA9
  • Octal nguyên thủy escapes bắt đầu bởi "\0o" và được gán thêm bằng một hay nhiều chữ số, ví dụ \0o251

Điều này có nghĩa là một mẫu được gắn thẻ như sau là có vấn đề, bởi vì mỗi ngữ pháp ECMAScript, một phân tích trông như đúng trình tự Unicode escape:

latex`\unicode`
// Throws in older ECMAScript versions (ES2016 and earlier)
// SyntaxError: malformed Unicode character escape sequence

ES2018 sửa đổi các chuỗi thoát bất hợp pháp

Các mẫu được gắn thẻ sẽ cho phép nhúng các ngôn ngữ (ví dụ DSLs, or LaTeX), trong đó các chuỗi thoát khác là phổ biến. ECMAScript đề xuất Template Literal Revision (giai đoạn 4, được tích hợp trong tiêu chuẩn ECMAScript 2018) xóa giới hạn cú pháp của chuỗi thoát ECMAScript khỏi các mẫu được gắn thẻ.

Tuy nhiên, các chuỗi thoát bất hợp pháp vẫn phải được giữ lại. Chúng sẽ hiển thị như thành phần undefined trong mảng “cooked”:

function latex(str) { 
 return { "cooked": str[0], "raw": str.raw[0] }
} 

latex`\unicode`

// { cooked: undefined, raw: "\\unicode" }

Chú ý rằng hạn chế trình tự thoát chỉ được loại bỏ khỏi các mẫu được gắn thẻ chứ không phải từ các mẫu chữ không được đánh dấu:

let bad = `bad escape sequence: \unicode`;

Thông số kỹ thuật

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Template Literals' in that specification.
Standard Initial definition. Defined in several section of the specification: Template Literals, Tagged Templates
ECMAScript Latest Draft (ECMA-262)
The definition of 'Template Literals' in that specification.
Draft Defined in several section of the specification: Template Literals, Tagged Templates

Browser compatibility

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Template literalsChrome Full support 41Edge Full support 12Firefox Full support 34IE No support NoOpera Full support 28Safari Full support 9WebView Android Full support 41Chrome Android Full support 41Firefox Android Full support 34Opera Android Full support 28Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Escape sequences allowed in tagged template literals
Experimental
Chrome Full support 62Edge No support NoFirefox Full support 53IE No support NoOpera Full support 49Safari Full support 11WebView Android Full support 62Chrome Android Full support 62Firefox Android Full support 53Opera Android Full support 46Safari iOS Full support 11Samsung Internet Android Full support 8.0nodejs Full support 8.10.0

Legend

Full support  
Full support
No support  
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.

See also