Học bằng cách đọc theo thứ tự

Chuỗi và Template Literal

Học chuỗi trong JavaScript: chọn kiểu dấu ngoặc, nhúng giá trị bằng template literal, tách và thay thế.

Văn bản bạn hiển thị trên màn hình, dữ liệu nhập từ form, tên sản phẩm trả về từ một API — rất nhiều giá trị mà một ứng dụng web xử lý là chuỗi (string) (giá trị gồm một dãy ký tự).

Bài này nói về xây dựng chuỗi với 3 kiểu dấu ngoặc và template literal, rồi các phương thức để dọn dữ liệu nhập thành dạng hiển thị được: cắt khoảng trắng, kiểm tra có chứa gì không, tách và ghép lại, và căn chỉnh chữ số.

Xây Dựng và Dọn Dẹp Chuỗi — 3 Kiểu Dấu Ngoặc và Template Literal

Giả sử bạn muốn màn hình xác nhận đơn hàng hiện "Insulated Mug x 3 / Total 3600" — tên sản phẩm, số lượng, và số tiền mỗi thứ nằm trong biến riêng. Ghép chúng thành một câu chính là việc xây dựng chuỗi. Hãy bắt đầu với cách viết một chuỗi trước tiên.

Một chuỗi được viết bọc trong nháy đơn ', nháy kép ", hoặc backtick. Nếu chính ký tự nháy bạn dùng để bọc xuất hiện bên trong, nó sẽ bị đọc là kết thúc chuỗi, nên để chứa ký tự nháy bên trong, hoặc bọc bằng kiểu nháy khác hoặc đặt \ trước nó để hủy ý nghĩa đặc biệt.

Bạn sẽ thấy một backtick thật trong ví dụ code sắp tới.

So Sánh 3 Kiểu Dấu Ngoặc
Nháy đơn' 'Nháy kép OKkhi ở bên trong'Staff "pick"'Nháy kép" "Nháy đơn OKkhi ở bên trong"It's here"Backtick${ } nhúnggiá trị${productName}x ${quantity}
Ký tự nháy nào bạn có thể viết nguyên trạng bên trong phụ thuộc vào bạn bọc chuỗi bằng gì. Chỉ backtick cho phép nhúng giá trị.
const productName = "Insulated Mug";   // bọc bằng nháy kép
const categoryName = 'Kitchen Goods';   // bọc bằng nháy đơn

// Thoát bằng \ để chứa cùng loại nháy bạn đã dùng để bọc
const notice = "Staff \"Pick\"";

// Bọc bằng loại nháy khác thì không cần thoát
const notice2 = 'Staff "Pick"';

console.log(productName.length);   // 13  số ký tự trả về dưới dạng số
console.log(notice);               // Staff "Pick"
console.log(notice2);              // Staff "Pick"

length, trả về số ký tự, là một property (thông tin gắn với một giá trị, đọc bằng tên mà không cần dấu ngoặc). Khác với một phương thức như toFixed ở bài trước, bạn không viết dấu ngoặc — không phải productName.length().

Chuỗi có thể nối bằng +, nhưng càng thêm nhiều biến, dấu nháy và dấu + càng chất chồng và khó đọc. Đó là lý do có template literal (bọc chuỗi trong backtick, và bất kỳ giá trị nào viết trong ${ } sẽ được nhúng vào).

Bên trong ${ } bạn có thể viết không chỉ một biến mà cả một biểu thức như unitPrice * quantity, và kết quả tính toán sẽ được nhúng vào.

Template Literal Nhúng Gì
${productName}Thay bằnggiá trị của nóInsulated Mug${unitPrice * 3}Tính trước,rồi thay vào3600Xuống dònggiữa chuỗiGiữ nguyênnhư đã viếtChuỗi2 dòng
Cái bên trong ${ } được tính trước, rồi ghép vào chuỗi. Xuống dòng giữ nguyên như đã viết.
const productName = "Insulated Mug";
const unitPrice = 1200;
const quantity = 3;

// Nối bằng + trộn lẫn nháy và +
console.log(productName + " x " + quantity + " / Total " + unitPrice * quantity);

// Với ${ }, cả giá trị lẫn biểu thức đều viết được nguyên trạng
console.log(`${productName} x ${quantity} / Total ${unitPrice * quantity}`);
// Cả hai in ra: Insulated Mug x 3 / Total 3600

Dọn Dẹp Để Hiển Thị — trim / slice / toUpperCase

Một cái tên gõ vào form có thể có khoảng trắng thừa xung quanh, hoặc chữ hoa/thường không nhất quán. Hiển thị nguyên trạng có thể trông như bị lỗi, nên bạn dọn dẹp hình dạng của nó ngay trước khi hiển thị.

trim bỏ khoảng trắng xung quanh, toUpperCase chuẩn hóa thành chữ hoa, và slice cắt một phần của chuỗi.

slice nhận vị trí bắt đầuvị trí kết thúc. Vị trí đếm từ 0, và ký tự tại vị trí kết thúc không được tính vào.

slice(0, 1) cho bạn ký tự đầu tiên; bỏ qua phần cuối, như slice(1), và bạn nhận mọi thứ từ đó đến hết chuỗi.

const rawInput = "  Minh  ";   // giá trị nhận từ một ô nhập liệu

console.log(rawInput.trim());               // Minh
console.log(rawInput.trim().length);        // 4
console.log(rawInput.trim().toUpperCase()); // MINH
console.log(rawInput.trim().slice(0, 2));   // Mi  2 ký tự đầu

// Bạn có thể nối các kết quả cắt lại bằng +
console.log(rawInput.trim().slice(0, 1).toUpperCase() + "…");  // M…

console.log(rawInput.length);               // 9  bản gốc vẫn còn khoảng trắng

Phương Thức Không Thay Đổi Chuỗi Gốc

trimtoUpperCase chỉ trả về kết quả đã dọn dẹp dưới dạng chuỗi mới — biến bạn gọi chúng trên đó giữ nguyên hoàn toàn. Để dùng kết quả, hãy lưu vào biến hoặc nối tiếp vào lần gọi phương thức kế tiếp, như trong ví dụ trên.

Dọn dẹp tên hiển thị từ một ô nhập liệu thành thứ có thể hiện trên màn hình. Tên hiển thị rawName và mã thành viên memberId đã được khai báo sẵn.

① Hiển thị tên đã bỏ khoảng trắng đầu và cuối.

② Hiển thị cùng tên đó với chỉ chữ cái đầu viết hoa.

③ Ghép mã thành viên và tên từ ② thành một lời chào duy nhất. Định dạng thành "Welcome, Hanh! (member #1042)".

(Nếu chạy đúng, phần giải thích sẽ xuất hiện.)

JavaScript / TypeScript Editor

Chạy code để xem đầu ra

Tìm Kiếm Bên Trong Chuỗi — includes / startsWith / indexOf

Nếu địa chỉ email người dùng gõ không có @, bạn sẽ muốn từ chối trước khi lưu. Hoặc có thể bạn muốn xử lý mã đơn hàng khác nhau tùy vào việc nó có bắt đầu bằng ORD- hay không. Những kiểm tra như thế này dùng các phương thức tìm kiếm bên trong chuỗi.

includes trả về true hoặc false cho một chuỗi cho trước có xuất hiện ở đâu đó không, và startsWith cho chuỗi có bắt đầu bằng nó không.

Khi bạn cần vị trí thật sự, dùng indexOf, trả về vị trí, dưới dạng số, của lần khớp đầu tiên. Nếu không có gì khớp, nó trả về -1, nên nó cũng đóng vai trò cách kiểm tra có chứa gì đó không.

Mỗi Phương Thức Chuỗi Trả Về Kiểu Gì
lengthindexOfĐếm ký tựhoặc vị tríNumbertrim / slicetoUpperCaseTạo ra mộtchuỗi đã dọnChuỗi mớiincludesstartsWithKiểm tra cókhớp khôngBoolean
Kết quả trả về tùy vào phương thức. Phương thức đếm trả về số, phương thức dọn dẹp trả về chuỗi mới, và phương thức kiểm tra trả về boolean (giá trị có 2 lựa chọn: true hoặc false).
const orderCode = "ORD-2026-0042";

console.log(orderCode.includes("2026"));    // true   có chứa ở đâu đó
console.log(orderCode.startsWith("ORD-"));  // true   phần đầu khớp

console.log(orderCode.indexOf("-"));        // 3      vị trí, đếm từ 0
console.log(orderCode.indexOf("SHIP"));     // -1     không tìm thấy

console.log(orderCode.slice(4));            // 2026-0042  từ vị trí 4 đến hết

Kết hợp vị trí mà indexOf trả về với slice, và bạn có thể lấy ra đúng phần sau một ký tự phân cách. Một khi biết @ nằm ở đâu, truyền cho slice vị trí ngay sau đó sẽ cho bạn phần domain của một địa chỉ email.

Kiểm tra một địa chỉ email gõ vào form đăng ký. Địa chỉ liên hệ đã đăng ký contactEmail và chuỗi gõ vào ô nhập, typedEmail, đã được khai báo sẵn.

① Hiển thị typedEmail có chứa ký tự @ không.

② Hiển thị phần domain của contactEmail — mọi thứ sau ký tự @.

③ Hiển thị contactEmail có bắt đầu bằng sato không.

JavaScript / TypeScript Editor

Chạy code để xem đầu ra

Tách và Ghép Lại — split và join

Đôi khi, như một dòng CSV hay ô nhập tag, một chuỗi duy nhất chứa nhiều giá trị. Xử lý từng mục riêng lẻ nghĩa là tách theo ký tự phân cách, và làm ngược lại — để hiển thị — nghĩa là ghép chúng trở lại thành một. split làm việc tách; join làm việc ghép.

split nhận ký tự để tách theo. split(",") tách tại mỗi dấu phẩy, và kết quả trả về là một mảng (array) (nhiều giá trị xếp theo thứ tự và gói vào một giá trị). join chạy theo hướng ngược lại — truyền cho nó ký tự để đặt giữa các mục, và nó ghép chúng lại thành một chuỗi duy nhất.

Vòng Lặp Qua Lại Giữa split và join
"1042,Mug,3"một chuỗisplit(",")tách ra1042 / Mug / 3tách thành 33 giá trịđã táchLấy vị trí 1để lấy 1 giá trịMugCùng 3giá trị đójoin(" | ")để ghép lại"1042 | Mug | 3"một chuỗi
split tách một chuỗi thành mảng tại ký tự phân cách; join đặt ký tự giữa các mảnh để ghép chúng lại thành một chuỗi.
const tagLine = "Kitchen,Insulated,Gift";   // nội dung một ô nhập tag

const tags = tagLine.split(",");   // tách tại mỗi dấu phẩy
console.log(tags.length);          // 3   số mảnh
console.log(tags[0]);              // Kitchen    vị trí 0 = giá trị đầu
console.log(tags[2]);              // Gift       vị trí 2 = giá trị thứ ba

console.log(tags.join(" / "));     // Kitchen / Insulated / Gift
console.log("2026-09-02".split("-").join("/"));  // 2026/09/02

Lấy Giá Trị Đã Tách Ra Theo Vị Trí

Từ mảng mà split trả về, lấy từng mục một bằng cách viết vị trí của nó, đếm từ 0, trong dấu ngoặc vuông — như tags[0]. Các thao tác trên chính mảng, như thêm hay bớt mục, sẽ nói lại trong bài về mảng.

Bạn nhận được các mục của một đơn hàng dưới dạng một dòng CSV. csvLine, một chuỗi có mã thành viên, tên sản phẩm, đơn giá, và số lượng ngăn bởi dấu phẩy, đã được khai báo sẵn.

① Hiển thị bạn nhận được bao nhiêu trường sau khi tách theo dấu phẩy.

② Hiển thị chỉ tên sản phẩm từ các trường đã tách.

③ Ghép lại tất cả các trường với " | " ở giữa và hiển thị trên một dòng.

JavaScript / TypeScript Editor

Chạy code để xem đầu ra

Thay Thế và Đệm — replaceAll và padStart

Có thể bạn muốn bỏ dấu gạch ngang khỏi một số điện thoại trước khi lưu, hoặc đệm một mã đơn hàng thành 6 chữ số với số 0 phía trước để hiển thị. Với các việc "định dạng lại một chuỗi nhận được thành một khuôn cố định" như thế này, dùng replaceAllpadStart.

replaceAll nhận chuỗi cần tìmchuỗi để thay thế. Thay bằng một chuỗi rỗng "" (chuỗi độ dài 0, không có gì giữa hai dấu nháy), và điều đó có tác dụng như xóa ký tự.

padStart nhận độ dài mục tiêuký tự để đệm (mặc định là dấu cách nếu bạn bỏ qua), và thêm ký tự đệm đó vào phía trước cho đủ độ dài còn thiếu. Nếu chuỗi gốc đã đủ dài hoặc dài hơn, không có gì được thêm vào — nó trả về nguyên trạng.

replaceAll và padStart Trả Về Gì
"090-1234-5678"replaceAll thaymọi lần khớp"09012345678""72"padStart đệm đầuthành 6 chữ số"000072""1234567"Đã 6+ chữ số,không đệm"1234567"
Không cái nào thay đổi chuỗi gốc — cả hai đều trả về kết quả đã sửa dưới dạng chuỗi mới.
const rawCode = "ord 2026 0042";   // mã đơn hàng gõ với khoảng trắng

console.log(rawCode.replaceAll(" ", "-"));  // ord-2026-0042
console.log("090-1234-5678".replaceAll("-", ""));  // 09012345678

console.log("42".padStart(6, "0"));   // 000042  đệm 0 cho đủ 6 chữ số
console.log("42".padStart(6));        //     42  không có ký tự đệm nghĩa là dấu cách
console.log("1200".padStart(3, "0")); // 1200    đã đủ 3+ chữ số, không đổi

Định dạng lại một mã đơn hàng được cấp và một số điện thoại gõ vào thành dạng có thể lưu. Mã đơn hàng orderNumber và số điện thoại rawPhone đã được khai báo sẵn.

① Hiển thị mã đơn hàng đã đệm thành 6 chữ số với số 0 phía trước.

② Hiển thị một mã đơn hàng thêm ORD- vào trước kết quả của ①.

③ Hiển thị số điện thoại đã bỏ hết dấu gạch ngang.

JavaScript / TypeScript Editor

Chạy code để xem đầu ra
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Với const quantity = 3;, thứ gì được nhúng vào chỗ ${quantity * 1200} xuất hiện trong một template literal?

Câu 2Đoạn code này hiển thị gì?
const rawName = " hanh ";
rawName.trim();
console.log(rawName.length);

Câu 3console.log("1234567".padStart(6, "0")); hiển thị gì?