Mục lục
Mục lục
Chào các bạn, lại là mình đây! Tiếp nối series “Javascript tuyển tập”, sau khi đã cùng nhau khám phá về các kiểu dữ liệu trong JavaScript nói chung, đặc biệt là sự khác biệt quan trọng giữa Primitive (Nguyên thủy) và Reference (Tham chiếu) mà chúng ta đã tìm hiểu kỹ ở phần 5, mình đã nói rằng phần tiếp theo có thể sẽ đi sâu vào kiểu dữ liệu Number. Tuy nhiên, hôm nay chúng ta sẽ cùng nhau đào sâu vào một kiểu dữ liệu nguyên thủy cực kỳ phổ biến và thiết yếu khác trong lập trình web: Chuỗi (Strings). Chuỗi là thứ chúng ta gặp và làm việc với rất nhiều trong lập trình, từ xử lý văn bản nhập vào, hiển thị thông báo, đến làm việc với dữ liệu từ API. Nắm vững cách thao tác với chuỗi sẽ giúp code của bạn linh hoạt và hiệu quả hơn nhiều đó nha!
Chuỗi trong JavaScript là một kiểu dữ liệu nguyên thủy (primitive type). Chuỗi đại diện cho các chuỗi ký tự. Một đặc điểm rất quan trọng cần ghi nhớ là chuỗi là immutable. Điều này có nghĩa là sau khi một chuỗi được tạo ra, bạn không thể thay đổi nội dung của nó trực tiếp tại chỗ. Mọi thao tác “thay đổi” chuỗi thực chất là tạo ra một chuỗi mới với nội dung đã được biến đổi, còn chuỗi ban đầu vẫn giữ nguyên. Bạn cần gán kết quả của phép biến đổi đó vào một biến mới hoặc biến ban đầu để thấy được sự thay đổi. Chuỗi được sử dụng rộng rãi trong xử lý dữ liệu, đặc biệt là xử lý văn bản.
let originalString = 'Hello';
console.log(originalString); // Output: Hello
// Thử "thay đổi" chuỗi bằng phương thức (thực chất là tạo chuỗi mới)
let modifiedString = originalString.toUpperCase();
console.log(modifiedString); // Output: HELLO
// Chuỗi gốc không bị ảnh hưởng
console.log(originalString); // Output: Hello
// Nếu muốn biến ban đầu thay đổi, phải gán lại
originalString = originalString.toLowerCase();
console.log(originalString); // Output: hello
JavaScript cung cấp một bộ công cụ phong phú (thuộc tính và phương thức) giúp chúng ta thao tác với chuỗi một cách dễ dàng.
Để biết một chuỗi có bao nhiêu ký tự, chúng ta sử dụng thuộc tính length. Ý nghĩa: Xác định số lượng ký tự có trong chuỗi.
let message = 'Xin chào!';
console.log(message.length); // Output: 9
Bạn có thể truy cập từng ký tự trong chuỗi tương tự như truy cập phần tử trong mảng, thông qua chỉ số (index) bắt đầu từ 0, hoặc sử dụng phương thức charAt(index). Ý nghĩa: Lấy từng ký tự cụ thể tại một vị trí trong chuỗi.
let text = 'JavaScript';
console.log(text); // Output: J (Truy cập bằng chỉ số)
console.log(text.charAt(1)); // Output: a (Truy cập bằng charAt)
console.log(text); // Output: undefined (Chỉ số vượt quá độ dài)
console.log(text.charAt(10)); // Output: (charAT trả về chuỗi rỗng nếu vượt quá)
Để ghép nhiều chuỗi thành một chuỗi hoàn chỉnh, bạn có thể sử dụng toán tử + hoặc phương thức concat(). Ý nghĩa: Kết hợp nội dung của nhiều chuỗi lại với nhau. Toán tử + cũng có thể dùng để nối chuỗi và số.
let part1 = 'Hello';
let part2 = ' ';
let part3 = 'World';
let fullString = part1 + part2 + part3;
console.log(fullString); // Output: Hello World
let anotherFullString = part1.concat(part2, part3);
console.log(anotherFullString); // Output: Hello World
console.log('The number is ' + 10); // Output: The number is 10 (Nối chuỗi với số)
Để trích xuất một phần (chuỗi con) từ một chuỗi, chúng ta sử dụng các phương thức như slice() hoặc substring(). Ý nghĩa: Lấy một đoạn ký tự từ vị trí bắt đầu đến vị trí kết thúc mong muốn.
slice(startIndex, endIndex): Trích xuất từ startIndex đến endIndex - 1. Có thể nhận chỉ số âm (đếm từ cuối chuỗi).
substring(indexA, indexB): Trích xuất giữa indexA và indexB (không bao gồm ký tự tại indexB). Tự động hoán đổi nếu indexA > indexB. Không nhận chỉ số âm .
let sentence = 'Learning JavaScript is fun';
// slice()
console.log(sentence.slice(0, 8)); // Output: Learning
console.log(sentence.slice(9)); // Output: JavaScript is fun (Cắt từ index 9 đến hết)
console.log(sentence.slice(-3)); // Output: fun (Chỉ số âm)
console.log(sentence.slice(9, -4)); // Output: JavaScript is (Cắt từ index 9 đến 4 ký tự cuối)
// substring()
console.log(sentence.substring(0, 8)); // Output: Learning
console.log(sentence.substring(9)); // Output: JavaScript is fun (Cắt từ index 9 đến hết)
console.log(sentence.substring(8, 0)); // Output: Learning (Tự động hoán đổi 8 và 0)
// console.log(sentence.substring(-3)); // Không hoạt động như slice với số âm
JavaScript cung cấp các phương thức tiện lợi để thay đổi định dạng chữ của chuỗi: toUpperCase() để chuyển toàn bộ thành chữ hoa và toLowerCase() để chuyển toàn bộ thành chữ thường. Ý nghĩa: Dễ dàng chuẩn hóa hoặc thay đổi cách hiển thị của chuỗi.
let mixedCase = 'HoC JaVaScRiPt ThẬt Dé';
console.log(mixedCase.toUpperCase()); // Output: HỌC JAVASCRIPT THẬT DÉ
console.log(mixedCase.toLowerCase()); // Output: học javascript thật dé
Để xác định vị trí của một chuỗi con bên trong một chuỗi lớn, kiểm tra sự tồn tại của nó, hoặc thay thế một phần nội dung của chuỗi, chúng ta có các phương thức như indexOf(), lastIndexOf(), includes(), và replace().
indexOf(sub): Trả về vị trí xuất hiện đầu tiên của chuỗi con trong chuỗi. Nếu không tìm thấy, trả về -1.
lastIndexOf(sub): Trả về vị trí xuất hiện cuối cùng của chuỗi con. Nếu không tìm thấy, trả về -1.
includes(sub): Kiểm tra xem chuỗi con có tồn tại trong chuỗi hay không, trả về true hoặc false. Hữu ích khi chỉ cần biết sự tồn tại chứ không cần vị trí.
replace(a, b): Thay thế lần xuất hiện đầu tiên của chuỗi con a bằng chuỗi b. Để thay thế tất cả các lần xuất hiện, bạn cần sử dụng Biểu thức chính quy (Regex) với cờ g. Ý nghĩa: Xác định vị trí, kiểm tra sự tồn tại hoặc thay thế trong chuỗi.
let sentence = 'Hello world, welcome to the world of JavaScript!';
console.log(sentence.indexOf('world')); // Output: 6
console.log(sentence.lastIndexOf('world')); // Output: 27
console.log(sentence.includes('JavaScript')); // Output: true
console.log(sentence.includes('Python')); // Output: false
console.log(sentence.replace('world', 'universe')); // Output: Hello universe, welcome to the world of JavaScript!
// Để thay thế tất cả, dùng Regex:
console.log(sentence.replace(/world/g, 'universe')); // Output: Hello universe, welcome to the universe of JavaScript!
Phương thức trim() được sử dụng để xóa bỏ các ký tự trắng (khoảng cách, tab, xuống dòng) dư thừa ở đầu và cuối chuỗi. Ý nghĩa: Xóa bỏ ký tự trắng dư ở đầu/cuối chuỗi. Giúp làm sạch dữ liệu chuỗi nhập vào.
let userInput = ' This is messy data. ';
console.log(userInput.trim()); // Output: "This is messy data."
Chuỗi thường cần được chuyển đổi sang các kiểu dữ liệu khác và ngược lại.
Số sang chuỗi: Có thể sử dụng phương thức toString() hoặc một mẹo nhỏ là nối chuỗi rỗng ‘’ với số.
Chuỗi sang số: Các hàm phổ biến là parseInt() (chuyển thành số nguyên) và parseFloat() (chuyển thành số thực). Lưu ý: Các hàm này sẽ dừng phân tích khi gặp ký tự không phải số. NaN (Not a Number) sẽ trả về nếu chuỗi không bắt đầu bằng số. Ý nghĩa: Chuyển đổi giữa kiểu chuỗi và số, rất phổ biến trong xử lý dữ liệu.
// Số sang chuỗi
let num = 123;
console.log(num.toString()); // Output: "123" (type: string)
console.log('' + num); // Output: "123" (type: string)
// Chuỗi sang số
let strNumInt = '456';
let strNumFloat = '78.9';
let strMixed = '10px';
let strInvalid = 'hello';
console.log(parseInt(strNumInt)); // Output: 456 (type: number)
console.log(parseFloat(strNumFloat)); // Output: 78.9 (type: number)
console.log(parseInt(strMixed)); // Output: 10 (Dừng ở 'p')
console.log(parseFloat(strMixed)); // Output: 10 (Dừng ở 'p')
console.log(parseInt(strInvalid)); // Output: NaN
Phương thức split() cho phép chia một chuỗi thành một mảng các chuỗi con dựa trên một ký tự phân tách (delimiter) được chỉ định. Nếu không truyền ký tự phân tách, toàn bộ chuỗi sẽ là một phần tử của mảng. Nếu truyền chuỗi rỗng ‘’ làm ký tự phân tách, mỗi ký tự trong chuỗi sẽ là một phần tử của mảng. Ý nghĩa: Chia chuỗi thành mảng dựa trên ký tự phân tách. Tách dữ liệu trong chuỗi thành các phần tử riêng biệt để dễ dàng xử lý dưới dạng mảng.
let csvData = 'apple,banana,cherry,date';
let words = 'Hello World';
let characters = 'JavaScript';
console.log(csvData.split(',')); // Output: ["apple", "banana", "cherry", "date"]
console.log(words.split(' ')); // Output: ["Hello", "World"]
console.log(characters.split('')); // Output: ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]
console.log(csvData.split()); // Output: ["apple,banana,cherry,date"]
Khi bạn muốn chèn các ký tự đặc biệt như dấu nháy đơn ('), dấu nháy kép ("), hoặc dấu gạch chéo ngược () vào trong một chuỗi mà không làm lỗi cú pháp, bạn cần sử dụng dấu gạch chéo ngược \ làm ký tự thoát (escape character). Ví dụ: ', ", . Ý nghĩa: Cho phép biểu diễn các ký tự có ý nghĩa đặc biệt trong cú pháp chuỗi như ký tự thông thường. Cho phép chèn dấu đặc biệt mà không bị lỗi cú pháp.
// Sử dụng dấu nháy kép bên trong chuỗi nháy đơn
let singleQuoteString = 'Anh ấy nói: "Chào bạn!"';
console.log(singleQuoteString); // Output: Anh ấy nói: "Chào bạn!"
// Sử dụng dấu nháy đơn bên trong chuỗi nháy kép
let doubleQuoteString = "Hôm nay trời 'đẹp' quá!";
console.log(doubleQuoteString); // Output: Hôm nay trời 'đẹp' quá!
// Nếu dùng cùng loại dấu nháy, cần ký tự thoát
let escapedSingle = "Hôm nay trời 'đẹp' quá!";
console.log(escapedSingle); // Output: Hôm nay trời 'đẹp' quá!
let escapedDouble = 'Anh ấy nói: "Chào bạn!"';
console.log(escapedDouble); // Output: Anh ấy nói: "Chào bạn!"
// Dấu gạch chéo ngược cũng cần thoát
let path = 'C:\\Program Files\\MyApp';
console.log(path); // Output: C:\Program Files\MyApp
// Các ký tự thoát phổ biến khác: \n (xuống dòng), \t (tab)
console.log('Dòng 1\nDòng 2');
console.log('Cột 1\tCột 2');
Ngoài các phương thức cơ bản, JavaScript còn có nhiều phương thức làm việc với chuỗi mạnh mẽ hơn:
charCodeAt(index): Lấy mã Unicode của ký tự tại một vị trí xác định. Hữu ích khi làm việc với các ký tự đặc biệt hoặc phân tích mã ký tự.
localeCompare(str2): So sánh hai chuỗi dựa trên quy tắc sắp xếp của ngôn ngữ bản địa (locale). Trả về một số âm (chuỗi gọi đến đứng trước str2), số dương (chuỗi gọi đến đứng sau str2), hoặc 0 (hai chuỗi bằng nhau theo locale).
match(), search(), split(), replace() (với Regex): Làm việc với Biểu thức chính quy (Regular Expressions - Regex) để tìm kiếm, khớp mẫu, chia tách và thay thế nâng cao trong chuỗi. Regex là một chủ đề riêng rất mạnh mẽ để xử lý các mẫu văn bản phức tạp. Ý nghĩa: Các phương thức này có ứng dụng trong phân tích, kiểm tra, tìm kiếm và xử lý chuỗi nâng cao. Nhìn chung, các thuộc tính và phương thức chuỗi giúp thao tác dữ liệu văn bản, tìm kiếm, thay đổi, định dạng, chuyển đổi, phân tích dễ dàng – hữu ích trong đa số ứng dụng thực tiễn như làm việc với form (kiểm tra định dạng email, số điện thoại), dữ liệu nhập từ người dùng, xử lý dữ liệu từ API (JSON thường là chuỗi), phân tích văn bản.
Để thực sự nắm vững cách sử dụng các phương thức chuỗi, cách tốt nhất là thực hành. Bạn có thể test nhanh bằng cách sử dụng trình duyệt, mở console (Dev Tools) và gõ code trực tiếp để xem kết quả. Sử dụng console.log() cũng là một cách tuyệt vời để kiểm tra giá trị của chuỗi sau mỗi thao tác. Khi gặp một phương thức mới lạ hoặc muốn hiểu chi tiết hơn về cách một phương thức hoạt động, đừng ngại khuyến khích sử dụng Google để tìm hiểu! Tài liệu MDN Web Docs là một nguồn rất đáng tin cậy.
Chuỗi là dạng dữ liệu cực kỳ quan trọng trong lập trình JavaScript. Bộ công cụ (các phương thức & thuộc tính) mà JavaScript cung cấp cho chuỗi rất phong phú và mạnh mẽ. Việc nắm vững chúng giúp bạn thao tác với dữ liệu văn bản một cách cực kỳ linh hoạt và hiệu quả trong mọi ứng dụng. Hãy luôn lưu ý: Vì chuỗi là immutable nên mọi thao tác “thay đổi” đều trả về chuỗi mới – chuỗi gốc không bị thay đổi. Bạn cần gán kết quả của phép biến đổi đó vào một biến mới hoặc biến ban đầu để thấy được sự thay đổi.
| Phương thức | Chức năng chính | Ví dụ |
|---|---|---|
| .length | Lấy số lượng ký tự | str.length |
| charAt(index) | Lấy ký tự ở vị trí xác định | str.charAt(2) |
| slice(start, end) | Lấy chuỗi con | str.slice(0, 5) |
| substring(a, b) | Tương tự slice nhưng ko nhận số âm | str.substring(1, 4) |
| toUpperCase() | Chuyển toàn bộ thành chữ hoa | str.toUpperCase() |
| toLowerCase() | Chuyển toàn bộ thành chữ thường | str.toLowerCase() |
| trim() | Xóa khoảng trắng đầu/cuối | str.trim() |
| replace(a, b) | Thay thế chuỗi con (đầu tiên) | str.replace('a', 'b') |
| includes(sub) | Kiểm tra chuỗi con có tồn tại | str.includes('abc') |
| split() | Chia chuỗi thành mảng | str.split(',') |
| concat(str2) | Nối chuỗi | str.concat('abc') |
| indexOf(sub) | Vị trí xuất hiện đầu chuỗi con | str.indexOf('a') |
| lastIndexOf(sub) | Vị trí cuối cùng của chuỗi con | str.lastIndexOf('a') |
| parseInt(), parseFloat() | Đổi chuỗi thành số | parseInt('123') |
| charCodeAt(index) | Lấy mã Unicode của ký tự | str.charCodeAt(0) |
| localeCompare(str2) | So sánh 2 chuỗi theo locale | str1.localeCompare(str2) |
| match(regex), search(regex) | Làm việc với Regex | str.match(/\+/g) |
Vậy là chúng ta đã cùng nhau đi qua những kiến thức cơ bản và quan trọng về Chuỗi trong JavaScript, từ đặc điểm immutable đến các phương thức thao tác dữ liệu văn bản. Nắm vững những điều này là chìa khóa để các bạn làm việc hiệu quả với dữ liệu văn bản trong các ứng dụng của mình. JavaScript có bộ công cụ phong phú cho xử lý chuỗi. Nắm được các thuộc tính/phương thức cơ bản và nâng cao sẽ giúp bạn thao tác với dữ liệu văn bản cực kỳ linh hoạt, mạnh mẽ và hiệu quả trong mọi ứng dụng. Cảm ơn các bạn đã dành thời gian đọc bài viết này! Hẹn gặp lại các bạn ở phần tiếp theo, có thể chúng ta sẽ đi sâu hơn vào kiểu dữ liệu Number hoặc một chủ đề thú vị khác nữa! (Nếu mình không lười :D)