Bài 12. Map, Set, iterator và generator

Ngoài mảng và đối tượng, JavaScript hiện đại có Map, Set, giao thức lặp (iterator) và generator. Bài này giúp chọn đúng cấu trúc dữ liệu và xử lý dãy dữ liệu lớn một cách tiết kiệm.

45 phútTrung cấp
Bạn sẽ học được
  • Dùng Map, Set và các phép tập hợp mới
  • Hiểu giao thức iterable/iterator
  • Viết generator với function* và yield
  • Dùng các phương thức mảng không thay đổi dữ liệu gốc
Thuật ngữ cần biết
Map
Bộ khóa–giá trị, khóa có thể là kiểu bất kỳ, giữ thứ tự chèn.
Set
Tập hợp các giá trị không trùng.
Iterable
Đối tượng duyệt được bằng for...of.
Generator
Hàm có thể tạm dừng (yield) và tiếp tục.

Khái niệm và lý thuyết

Đối tượng thường ({}) chỉ có khóa chuỗi/symbol và lẫn với thuộc tính kế thừa. Map phù hợp khi khóa động, thêm xóa thường xuyên, cần biết kích thước (size). Set loại trùng tự động và kiểm tra tồn tại rất nhanh (O(1)).

Mọi thứ dùng được với for...of, spread ... đều là iterable. Generator tạo iterator một cách dễ dàng và lười (lazy): chỉ tính phần tử khi cần, nên có thể biểu diễn dãy vô hạn.

Map và Set

const soLanXem = new Map();
for (const trang of ["home", "blog", "home"]) {
  soLanXem.set(trang, (soLanXem.get(trang) ?? 0) + 1);
}
console.log([...soLanXem]);          // [["home",2],["blog",1]]

const a = new Set([1, 2, 3]), b = new Set([2, 3, 4]);
a.union(b);          // {1,2,3,4}
a.intersection(b);   // {2,3}
a.difference(b);     // {1}
const khongTrung = [...new Set([1, 1, 2, 3, 3])]; // [1,2,3]

// Gom nhóm (ES2024)
const ds = [{ ten: "An", lop: "A" }, { ten: "Bình", lop: "B" }, { ten: "Chi", lop: "A" }];
Object.groupBy(ds, sv => sv.lop);   // { A: [...], B: [...] }

Generator

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) { yield a; [a, b] = [b, a + b]; }
}
const it = fibonacci();
console.log(it.next().value, it.next().value, it.next().value); // 0 1 1

// Iterator helpers: xử lý lười trên dãy vô hạn
const dau10SoChan = fibonacci().filter(x => x % 2 === 0).take(10).toArray();

Phương thức mảng không đột biến

Cũ (sửa mảng gốc)Mới (trả mảng mới)
sort()toSorted()
reverse()toReversed()
splice()toSpliced()
a[i] = xwith(i, x)

Các phương thức mới rất hữu ích trong React/Vue, nơi trạng thái không được sửa trực tiếp. Thêm nữa: at(-1) lấy phần tử cuối, findLast(), structuredClone() sao chép sâu.

Mẹo hay

Khi cần tra cứu nhiều lần “phần tử có trong danh sách không”, chuyển mảng sang Set một lần để tăng tốc rõ rệt.

Lưu ý

JSON.stringify không hỗ trợ Map/Set (ra {}). Chuyển sang mảng hoặc đối tượng trước: Object.fromEntries(map).

Thực hành
  1. Đếm tần suất từ trong một đoạn văn bằng Map, in 5 từ nhiều nhất.
  2. Tìm môn học chung giữa hai sinh viên bằng Set.intersection.
  3. Viết generator sinh số nguyên tố, lấy 20 số đầu.
  4. Gom danh sách sản phẩm theo danh mục bằng Object.groupBy.
Tóm tắt bài học
  • Map cho khóa–giá trị động; Set cho tập không trùng.
  • for...of và spread làm việc với mọi iterable.
  • Generator tạo dãy lười, kể cả vô hạn.
  • Ưu tiên phương thức mảng không đột biến.