Trong JS, Map và Object đều dùng để lưu trữ các cặp Key-Value, nhưng chúng khác nhau đáng kể về chức năng, hiệu suất và trường hợp sử dụng
| Đặc điểm | Map | Object |
| Loại key | Có thể là bất kỳ kiểu dữ liệu nào (ví dụ: chuỗi, số, đối tượng, hàm). | Key phải là chuỗi hoặc symbol (key không phải chuỗi sẽ được chuyển thành chuỗi). |
| Thứ tự của key | Duy trì thứ tự key theo thứ tự chèn vào. | Không đảm bảo thứ tự (mặc dù các engine JavaScript hiện đại thường duy trì thứ tự). |
| Duyệt qua | Có thể duyệt trực tiếp bằng các phương thức như forEach, keys() hoặc entries(). | Không thể duyệt trực tiếp; cần sử dụng các phương thức như Object.keys() hoặc for...in. |
| Thuộc tính kích thước | Có thuộc tính size để lấy số lượng phần tử. | Không có thuộc tính kích thước; phải dùng Object.keys(obj).length. |
| Hiệu suất | Tối ưu cho việc thêm/xóa cặp key-value thường xuyên. | Ít hiệu quả hơn khi cập nhật thường xuyên; phù hợp với dữ liệu tĩnh. |
| Key mặc định | Không có key mặc định. | Bao gồm các key mặc định từ prototype (ví dụ: toString). |
| Tuần tự hóa dữ liệu | Không hỗ trợ JSON trực tiếp (cần tuần tự hóa tùy chỉnh). | Hỗ trợ JSON trực tiếp qua JSON.stringify(). |
Map khi:Object khi:== (So sánh bằng không nghiêm ngặt)1console.log(3 == "3"); // true (chuỗi "3" được chuyển thành số 3)
2console.log(true == "1"); // true (true được chuyển thành số 1)
3console.log(null == undefined); // true (null và undefined được coi là bằng nhau)
4console.log(0 == false); // true (false được chuyển thành số 0)=== (So sánh bằng nghiêm ngặt)false.true nếu giá trị và kiểu dữ liệu của hai toán hạng giống hệt nhau.1console.log(3 === "3"); // false (kiểu dữ liệu khác nhau: number vs string)
2console.log(true === "1"); // false (kiểu dữ liệu khác nhau: boolean vs string)
3console.log(null === undefined); // false (null và undefined là các kiểu khác nhau)
4console.log(0 === false); // false (kiểu dữ liệu khác nhau: number vs boolean)So sánh trực tiếp giữa == và ===
| Đặc điểm | == (Không nghiêm ngặt) | === (Nghiêm ngặt) |
| Kiểu so sánh | So sánh giá trị sau khi chuyển đổi kiểu nếu cần | So sánh cả giá trị và kiểu dữ liệu |
| Chuyển đổi kiểu dữ liệu | Có | Không |
| Kết quả nếu khác loại | Có thể trả về true sau khi chuyển đổi | Luôn trả về false |
| Ví dụ: 3 và "3" | 3 == "3" trả về true | 3 === "3" trả về false |
Quy trình chuyển đổi data type ở ==
Omit là một Utility Type được sử dụng để tạo ra một kiểu dữ liệu mới từ một kiểu dữ liệu hiện có bằng cách loại bỏ một hoặc nhiều thuộc tính cụ thể. Đây là một công cụ hữu ích khi bạn muốn tái sử dụng kiểu dữ liệu nhưng không cần đến một số thuộc tính nhất định
Công dụng của Omit
Cách sử dụng Omit
1type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;Trong đó:
T là kiểu dữ liệu gốc.K là danh sách các thuộc tính (dưới dạng string hoặc union) cần loại bỏ.1interface User {
2 name: string;
3 age: number;
4 email: string;
5 address: string;
6}
7
8// Loại bỏ 'age' và 'address' khỏi User
9type PublicProfile = Omit<User, 'age' | 'address'>;
10
11const userProfile: PublicProfile = {
12 name: 'John Doe',
13 email: 'john@example.com',
14};
15Cú pháp Rest được dùng để gom các tham số còn lại vào trong một mảng. Nó thường xuất hiện trong định nghĩa hàm và luôn đặt ở cuối danh sách tham số
1function sum(a, b, ...rest) {
2 console.log(a); // Giá trị tham số đầu tiên
3 console.log(b); // Giá trị tham số thứ hai
4 console.log(rest); // Mảng chứa các tham số còn lại
5}
6
7sum(1, 2, 3, 4, 5);
8// Output:
9// 1
10// 2
11// [3, 4, 5]
12Cú pháp Spread được dùng để tách một mảng hoặc đối tượng thành các phần tử riêng lẻ. Nó thường xuất hiện trong lời gọi hàm, khi làm việc với mảng hoặc đối tượng
Ứng dụng phổ biến
1const arr = [1, 2, 3];
2console.log(...arr); // Output: 1 2 31const arr1 = [1, 2];
2const arr2 = [...arr1, 3, 4];
3console.log(arr2); // Output: [1, 2, 3, 4]1const obj = { a: 1, b: 2 };
2const objCopy = { ...obj }; // Sao chép đối tượng
3console.log(objCopy); // Output: { a: 1, b: 2 }Cú pháp Spread được triển khai dựa trên nguyên lý làm việc với các đối tượng iterable (có thể lặp), chẳng hạn như mảng, chuỗi hoặc các đối tượng có phương thức Symbol.iterator.
Cú pháp (…) sử dụng cơ chế iterator để duyệt qua từng phần tử trong một đối tượng iterable. Khi sử dụng spread, Js sẽ
Khi sử dụng với mảng, spread syntax tạo ra một bản sao nông (shallow copy) của mảng hoặc hợp nhất nhiều mảng thành một mảng mới. Điều này được thực hiện bằng cách lặp qua từng phần tử của mảng nguồn và thêm chúng vào mảng đích
Đối với đối tượng (Object iterals), spread syntax sao chép các thuộc tính enumerable (có thể liệt kê) từ đối tượng nguồn sang đối tượng đích. Điều này không yêu cầu Symbol.iterator, mà chỉ cần liệt kê các thuộc tính thông qua Object.keys
Bên trong JS engine
Example sử dụng satisfies trong NestJS (TS)
1type User = {
2 username: string;
3 age: number;
4};
5
6const joe = {
7 username: "joe_hiyden",
8 age: 30,
9} satisfies User; // OK
10
11const invalidUser = {
12 username: "joe_hiyden",
13} satisfies User; // Lỗi: thiếu thuộc tính 'age'
14Lợi ích khi dùng satisfies
unknown là một type đặc biệt trong ts, được giới thiệu ở phiên bản 3.0, dùng để biểu diễn một giá trị mà bạn chưa biết rõ kiểu dữ liệu cụ thể của nó tại thời điểm khai báo. Đây được xem là “phiên bản an toàn hơn” của kiểu any
Đặc điểm của unknown:
unknown1let value: unknown = "Hello";
2// value.toUpperCase(); // Error: Object is of type 'unknown'
3
4if (typeof value === "string") {
5 console.log(value.toUpperCase()); // OK
6}1let a: unknown = 25;
2let b: string = a; // Error
3let c: string = a as string; // OK nhờ type assertionKhi nào nên dùng unknown
So sánh nhanh với any
| Đặc điểm | any | unknown |
| Gán giá trị bất kỳ | Có | Có |
| Sử dụng trực tiếp | Có (không kiểm tra kiểu) | Không (phải kiểm tra kiểu trước) |
| Gán cho biến kiểu khác | Có | Không (trừ unknown hoặc any) |
| Độ an toàn | Thấp | Cao hơn |