Template Literal và Tagged Template

Template Literal

Một template literal có hai tính năng mới so với literal chuỗi.

Trước tiên, nó hỗ trợ string interpolation: nếu bạn đặt một biểu thức JavaScript trong ${}, nó được tính toán, chuyển thành chuỗi sau đó chèn vào chuỗi:

const MAX = 100;
function doSomeWork(x) {
  if (x > MAX) {
    throw new Error(`At most ${MAX} allowed: ${x}!`);
  }
  // ...
}
assert.throw(
  () => doSomeWork(101),
  { message: 'At most 100 allowed: 101!' }
);

Thứ hai, template literal có thể viết trên nhiều dòng:

const str = `this is
a text with
multiple lines`;

Template literal luôn luôn trả về một chuỗi.

Tagged template

Xét ví dụ sau:

function tagFunc(...args) {
  return args;
}

const setting = 'dark mode';
const value = true;

assert.equal(
  tagFunc`Setting ${setting} is ${value}!`, // (A)
  [['Setting ', ' is ', '!'], 'dark mode', true] // (B)
);

Biểu thức ở dòng (A) được gọi là tagged template. Nó tương đương với việc gọi hàm tagFunc với danh sách các đối số trong mảng ở dòng (B).

Hàm tagFunc khi gọi theo cách này được gọi là tag function. Các đối số của nó là:

  • Mảng chứa phần tĩnh của template literal (là các chuỗi bao quanh ${}). Trong ví dụ trên mảng này là: ['Setting ', ' is ', '!'].
  • Các phần tử động của template literal (là các giá trị trong ${}).

Với các đối số trên, tag function có thể xử lý và trả về bất cứ giá trị nào.

Raw string literal

Một chuỗi thô (raw string) có thể tạo qua tag function có tên là raw. Trong một chuỗi thô dấu backslash không đóng vai trò ký tự thoát mà được xem như một ký tự thông thường:

assert.equal(String.raw`\back`, '\\back');

Nó giúp ích khi dữ liệu văn bản có các dấu backslash. Ví dụ chuỗi biểu thức chính quy:

const regex1 = /^\./;
const regex2 = new RegExp('^\\.');
const regex3 = new RegExp(String.raw`^\.`);