Tự học lập trình Full Stack ngày 48/365: Template literals (Chuỗi mẫu trong JS)- P1
Chuỗi mẫu trong JavaScript
Normal string literals
hayNormal string
là các chuỗi thông thường khi chúng ta khai báo bình thường với“” hoặc ‘’.
Template literals
(còn được gọi với tên không chính thức làtemplate strings
, có thể dịch là “Chuỗi mẫu
”) được bao quanh bởi các ký tự dấu nháy ngượcbacktick `
thay vìdấu nháy kép “ ”
hoặcdấu nháy đơn ‘ ’. Ví dụ:
Một chuỗi thông thường 1 dòng (single-line string)
`string text`
Cũng có thể khai báo một single-line string, bằng cách viết trên nhiều dòng cho dễ đọc, bằng cách sử dụng dấu
backslash \:
let oneLineString = `Hà nội mùa thu \ cây bàng lá đỏ \ những ngôi nhà cổ \ mái ngói rêu phong`; console.log(onLineString); //"Hà nội mùa thu cây bàng lá đỏ những ngôi nhà cổ mái ngói rêu phong"
Mặc dù viết trên nhiều dòng nhưng nó là chuỗi 1 dòng.
Một chuỗi thông thường nhiều dòng
Nếu dùng khai báo thông thường với
“ hoặc ‘
thì cần dùng ký tự\n
để có 1 chuỗi nhiều dòng:
console.log("string text line 1\nstring text line 2"); // "string text line 1 // string text line 2"
Template literals
cho phép viết 1 chuỗi trên nhiều dòng mà không cần \n:
let multiLineString = `Hà nội mùa thu cây bàng lá đỏ những ngôi nhà cổ mái ngói rêu phong`; console.log(multiLineString ); //"Hà nội mùa thu //cây bàng lá đỏ //những ngôi nhà cổ //mái ngói rêu phong"
So với ví dụ trên, ta thấy nếu ta gõ Enter luôn thì sẽ tạo chuỗi nhiều dòng. Còn nếu dùng ký tự
\
rồi mới Enter thì sẽ tạo chuỗi 1 dòng bình thường.
Nội suy chuỗi với placeholder (Nội suy chuỗi String interpolation)
Ngoài việc có thể dùng để khai báo 1 chuỗi như cách thông thường dùng nháy đơn/nháy kép thì
Template literals
có thể dùng để chứa các phần khác nhau được gọi là placeholder, đó là các biểu thức được nhúng trong chuỗi mẫu với dạng${expression}. Ký hiệu $ chính là thông báo để JS tiến hành nội suy.
Ví dụ cú pháp như sau:
`stringtext1 ${expression} stringtext2`
Toàn bộ các thành phần bên trong chuỗi mẫu gồm
stringtext1 , stringtext2, placeholder
là${expression}
sẽ được truyền đến 1 hàm, hoặc là hàm mặc định (default function), hoặc là 1 hàm do chúng ta cung cấp.Khi mà chúng ta không cung cấp 1 hàm, thì hàm mặc định sẽ được sử dụng, khi đó nó chỉ thực hiện nội suy chuỗi (string interpolation), để thay thế các placeholders bằng các giá trị cụ thể và sau đó nối các thành phần lại với nhau thành 1 chuỗi duy nhất. Ví dụ
let name = "Nam"; let welcome = `My name is ${name}`; //biến name là biểu thức trong placeholder console.log(welcome); //My name is Nam
Sở dĩ
Template literals
thi thoảng được gọi với tên không chính thức làtemplate strings
bởi vì chúng thường được sử dụng cho việc nội suy chuỗi.
Nội suy chuỗi (string interpolation)
tức là việc tạo các chuỗi bằng cách thay thế các giá trị vào placeholders.To escape
${}
(chặn nội suy):Dùng
\${}
để ngăn việc nội suy biểu thức, thêm\
vào trước${}
:`\${1}` === "${1}"; // true
To escape backtick:
Để viết dấu backtick trong
Template literals
. Thêm\
vào trước`
`\`` === "`"; // true
Tầm quan trọng của Nội suy chuỗi (string interpolation)
Nếu không có template literals khi bạn muốn kết hợp các biểu thức (expression) với các chuỗi, bạn sẽ cần sử dụng nối chuỗi bằng toán tử
binary +:
const a = 5; const b = 10; console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + "."); // "Fifteen is 15 and // not 20."
Lưu ý ở ví dụ trên phải dùng cặp ngoặc đơn
()
để phép cộng số học được thực hiện trước khi thực hiện cộng chuỗi.Nhìn ví dụ trên khá là khó đọc, đặc biệt khi mà bạn có nhiều biểu thức .
Với template literals bạn có thể tránh các toán tử nối chuỗi, và cải thiện khả năng đọc của code - bằng cách sử dụng các placeholders có dạng
${expression}
để thực hiện thay thế cho các biểu thức được nhúng:
const a = 5; const b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); // "Fifteen is 15 and // not 20."
Mặc dù cả 2 phương pháp đều tạo ra chuỗi. Nhưng cách chuyển đổi giá trị về chuỗi lại khác nhau:
Template literals ép giá trị trong biểu thức của chúng trực tiếp thành chuỗi.
Còn toán tử cộng chuỗi thực hiện thêm bước: ép kiểu toán hạng sang dạng nguyên thủy trước, nối mới nối chuỗi.
Nesting templates (Các template literals lồng nhau)
Nesting template hay Nesting template literls là các chuỗi mẫu lồng nhau. Trong 1 số trường hợp nhất định, việc này sẽ giúp code dễ hơn và dễ đọc hơn để có được các chuỗi.
Bên trong chuỗi mẫu có các
${expression}
placeholderVà phần
expression
ta lại sử dụng các chuỗi mẫuHãy xem ví dụ sau:
Khi không sử dụng template literals
Nếu bạn muốn trả về 1 giá trị dựa trên 1 điều kiện nào đó, bạn có thể thực hiện như thế này. Trong ví dụ này sử dụng toán tử 3 ngôi với cú pháp:
điều_kiện ? biểu_thức_nếu_đúng : biểu_thức_nếu_sai;
Ví dụ này dùng toán tử 3 ngôi lồng nhau, được viết trên nhiều dòng.
Đầu tiên tạo 1
biến classes chứa chuỗi "header"
Sau đó sẽ cộng (nối) chuỗi
classes
với 1 giá trị, giá trị này sẽ tùy theo điều kiện sau đó.
Nếu hàm
isLargeScreen()
trả vềtrue
, thì thêm""
(tức là không thêm gì cả) vàoclasses
.Nếu
isLargeScreen()
trả vềfalse
, thì xét tiếp:
Nếu
item.isCollapsed
làtrue
, thêm chuỗi" icon-expander"
vàoclasses
.Nếu
item.isCollapsed
làfalse
, thêm chuỗi" icon-collapser"
vàoclasses
.
let classes = "header"; //Tạo biến classes chứa chuỗi "header" classes += isLargeScreen() ? "" : item.isCollapsed ? " icon-expander" : " icon-collapser";
Viết trên 1 dòng để cho dễ hiểu.
isLargeScreen()? "": (item.isCollapsed? " icon-expander" : " icon-collapser");
Nếu sử dụng template literal nhưng không nesting (không lồng nhau)
const classes = `header ${ isLargeScreen()?"": item.isCollapsed ?"icon-expander":"icon-collapser"}`;
Nếu sử dụng nesting of template literals (Các template literals lồng nhau)
const classes = `header ${ isLargeScreen() ? "" : `icon-${item.isCollapsed ? "expander" : "collapser"}` }`;
Tức là ở ví dụ này ta sử dụng template literals, bên trong của placeholder ta dùng toán tử 3 ngôi, và trong toán tử 3 ngồi ta lại dùng template literals