+2

JavaScript Map and Set

Map và Set là hai loại cấu trúc dữ liệu trong JavaScript mà bạn có thể sử dụng để lưu trữ một tập hợp các giá trị tương tự như Object hay Array. Đây là những cấu trúc dữ liệu chuyên biệt có thể giúp bạn lưu trữ và thao tác với các giá trị liên quan.

Trong bài viết này chúng ta sẽ tìm hiểu chi tiết về cách hoạt động của MapSet, khi nào nên sử dụng chúng. Chúng ta cũng sẽ khám phá các phương thức của đối tượng Map Set mới được thêm vào JavaScript gần đây.

1. Map Object

Đối tượng Map lưu trữ dữ liệu theo cấu trúc key/value giống với Object. Điểm khác biệt chính:

  • Map có thể dùng bất kì kiểu dữ liệu nào để làm key
  • Map duy trì thứ tự của dữ liệu mới được thêm vào

1-1. How to Create

Để khởi tạo một đối tượng Map ta sử dụng hàm khởi tạo (constructor) như sau:

const myMap = new Map();

1-2. Methods and Properties

Đối tượng Map có các phương thức và thuộc tính sau:

  • set(key, value) – Thêm một phần tử mới với key/value cụ thể vào Map. Nếu phần tử đó trùng với key đã tồn tại, nó sẽ được cập nhật với giá trị mới.
  • get(key) – Trả về giá trị value của key đó (returns undefined if key doesn't exist)
  • has(key) – Check xem Map có key đó hay không
  • delete(key) – Xóa một key cụ thể
  • clear() – Xóa tất cả các phần tử khỏi Map
  • keys() – Trả về tất cả các keys trong Map
  • values() – Trả về tất cả các values trong Map
  • entries() – Trả về tất cả các cặp key/value trong Map
  • size – Trả về số lượng các phần tử trong Map

Để insert data vào trong Map, chúng ta sử dụng phương thức set():

const myMap = new Map();

myMap.set(1, 'Jack');
myMap.set(2, 'Jill');
myMap.set('animal', 'Elephant');

Đoạn code trên tạo ra một đối tượng Map như sau:

Map(3)
0: {1 => "Jack"}
1: {2 => "Jill"}
2: {"animal" => "Elephant"}

Để get value từ đối tượng Map bạn có thể sử dụng phương thức get() và truyền key vào làm đối số:

console.log(myMap.get(1)); // Jack

console.log(myMap.get('animal')); // Elephant

Để kiểm tra xem có bao nhiêu phần tử trong Map, chúng ta sử dụng thuộc tính size

myMap.size; // 3

Để kiểm tra xem một key nào đó có tồn tại trong đối tượng Map hay không, chúng ta sử dụng phương thức has()

myMap.has(1); // true

myMap.has(10); // false

Nếu bạn muốn xóa một cặp key/value nào đó thì sử dụng phương thức delete() và truyền tên key muốn xóa

myMap.delete(1);

console.log(myMap);
// 0: {2 => "Jill"}
// 1: {"animal" => "Elephant"}

Còn đây là cách xóa toàn bộ sử dụng clear()

myMap.clear();

console.log(myMap);
// Map(0) {size: 0}

1-3. Other Ways to Create a Map Object

Bạn cũng có thể tạo ra đối tượng Map từ Array như sau:

const myMap = new Map([
  [1, 'Jack'],
  [2, 'Jill'],
  ['animal', 'Elephant'],
]);

Khi tạo Map từ Array, bạn phải tạo một mảng 2 chiều và chỉ định hai phần tử trong mỗi mảng con.

Phần tử đầu tiên sẽ là key, phần tử thứ hai sẽ là value. Bất kì giá trị dư thừa nào trong mảng con sẽ bị bỏ qua.

Ở ví dụ bên dưới, giá trị Johnson ở mảng đầu tiên sẽ bị bỏ qua (ignored)

const myMap = new Map([
  [1, 'Jack', 'Johnson'], // the value 'Johnson' is ignored
  [2, 'Jill'],
  ['animal', 'Elephant'],
]);

Vì ta có thể tạo ra đối tượng Map từ Array nên chúng ta cũng có thể tạo nó từ Object. Đầu tiên ta cần chuyển từ Object sang Array sử dụng phương thức Object.entries()

const person = {
    'name': 'Jack',
    'age': 20,
}

const myMap = new Map(Object.entries(person));

console.log(myMap); // Map(2) { 'name' => 'Jack', 'age' => 20 }

1-4. Iterate Map Object

Để duyệt qua các phần tử trong đối tượng Map ta có thể sử dụng phương thức forEach() hoặc vòng lặp for ... of

const myMap = new Map([
  [1, 'Jack'],
  [2, 'Jill'],
  ['animal', 'Elephant'],
]);

// iterate using the forEach() method
myMap.forEach((value, key) => {
  console.log(`${key}: ${value}`);
});

// or using the for .. of loop

for (const [key, value] of myMap) {
  console.log(`${key}: ${value}`);
}

Cả 2 cách đều cho ra chung output:

1: Jack
2: Jill
animal: Elephant

1-5. When to Use

Bạn có thể nghĩ đối tượng Map như là một phiên bản nâng cấp của Object thông thường. Nó có thể sử dụng bất kỳ loại dữ liệu nào làm key, trong khi Object thông thường chỉ dùng string làm key.

Bên trong đối tượng Map hoạt động hiệu quả hơn khi bạn cần thêm và xóa các key, vì vậy bạn có thể cân nhắc sử dụng nó khi dữ liệu của bạn thay đổi thường xuyên.

Ngoài ra, đối tượng Map có nhiều phương thức hữu ích cho việc thao tác dữ liệu, chẳng hạn như has() để kiểm tra xem Map có chứa một key cụ thể nào không, keys() để lấy tất cả các keys được định nghĩa trong Map, values để lấy tất cả các giá trị, và entries() để lấy tất cả các cặp key/value.

Tuy nhiên, nếu bạn chỉ muốn tạo một Object mà không cần thao tác gì thêm thì bạn không cần sử dụng đối tượng Map.

Một ví dụ là khi bạn gửi một yêu cầu mạng bằng phương thức fetch(). Bạn sẽ tạo một đối tượng và chuyển đổi nó thành chuỗi JSON, vì vậy việc sử dụng đối tượng Map sẽ không mang lại lợi ích gì.

2. Set Object

Đối tượng Set cho phép bạn lưu trữ một tập hợp các phần tử, giống như một Array. Những điểm khác biệt giữa Set và Array là:

  • Set yêu cầu tất cả các phần tử phải là duy nhất (unique)
  • Set có ít phương thức để thao tác dữ liệu hơn.

2-1. How to Create

Để khởi tạo một đối tượng Set ta sử dụng hàm khởi tạo (constructor) như sau:

const mySet = new Set();

2-2. Methods and Properties

Đối tượng Set có các phương thức và thuộc tính sau:

  • add(value) – Thêm giá trị
  • has(value) – Kiểm tra xem Set có chứa một giá trị cụ thể nào không
  • delete(value) – Xóa một giá trị cụ thể
  • clear() – Xóa toàn bộ giá trị
  • keys() – Trả về tất cả giá trị
  • values() – Trả về tất cả giá trị
  • entries() – Trả về tất cả giá trị dưới dạng Array [value, value]
  • size – Trả về số lượng phần tử trong Set

Lưu ý rằng keys()values() đều trả về chung kiểu output

const mySet = new Set(['Jack', 'Jill', 'John']);

console.log(mySet.entries());

Output:

[Set Entries] {
  [ 'Jack', 'Jack' ],
  [ 'Jill', 'Jill' ],
  [ 'John', 'John' ]
}

Lưu ý cách các giá trị được lặp lại một lần trong mỗi mảng ở trên. Phương thức entries() được tạo ra để làm cho Set giống với đối tượng Map, nhưng bạn có lẽ không cần đến nó.

Có thêm các phương thức mà bạn có thể sử dụng để tương tác với một đối tượng Set khác. Chúng ta sẽ thảo luận về chúng trong phần tiếp theo.

Để thêm một phần tử vào đối tượng Set, bạn có thể sử dụng phương thức add:

const mySet = new Set();

mySet.add(1);
mySet.add(2);
mySet.add(3);

console.log(mySet); // [1, 2, 3]

Lấy tất cả các giá trị trong Set

mySet.values(); // [Set Iterator] { 'Jack', 'Jill', 'John' }

Kiểm tra xem Set có chứa giá trị cụ thể nào hay không:

mySet.has('Jack'); // true

mySet.has('Michael'); // false

Cách xóa giá trị:

mySet.delete('Jill');

mySet.clear();

2-3. Composition Methods

Ngoài các phương thức thông thường ở trên, Set cũng có các phương thức kết hợp mà bạn có thể sử dụng để thực hiện các phép toán lý thuyết tập hợp như hiệu, hợp, và giao (difference, union, intersection)

Bảng tham khảo từ MDN Set documentation:

set-composition-methods.png

Ví dụ, bạn có thể lấy một tập hợp chứa các phần tử khác biệt giữa hai tập hợp như sau:

const setA = new Set([1, 2, 3, 4, 5]);

const setB = new Set([4, 5, 6, 7, 8]);

const diffsA = setA.difference(setB); // Set(3) {1, 2, 3}
const diffsB = setB.difference(setA); // Set(3) {6, 7, 8}

Ở đây, phương thức setA.difference(setB) trả về một Set chứa các giá trị chỉ có trong đối tượng setA.

Khi bạn chạy phương thức setB.difference(setA), các giá trị ngược lại sẽ được trả về.

Lưu ý rằng các phương thức này là những bổ sung mới cho JavaScript, và tính đến thời điểm này, chỉ có Safari 17 và Chrome 122 hỗ trợ các phương thức này.

Rất có thể, các phương thức này sẽ sớm có trong Node.js.

2-4. Iterate Set Object

Để duyệt qua các phần tử trong đối tượng Set ta có thể sử dụng forEach() hoặc vòng lặp for ... of

const mySet = new Set(['Jack', 'Jill', 'John']);

// iterate using the forEach() method
mySet.forEach(value => {
  console.log(value);
});

// or using the for .. of loop

for (const value of mySet) {
  console.log(value);
}

Output:

Jack
Jill
John

2-5. When to Use

Bạn có thể nghĩ đối tượng Set như là một phiên bản thay thế của Array thông thường.

Vì đối tượng Set bỏ qua các giá trị trùng lặp, bạn có thể sử dụng đối tượng này để loại bỏ các phần tử trùng lặp từ một mảng, sau đó chuyển đối tượng Set trở lại thành mảng:

const myArray = [1, 1, 2, 2, 3, 3];

const uniqueArray = [...new Set(myArray)];

console.log(uniqueArray); // [ 1, 2, 3 ]

Một lý do khác mà bạn có thể muốn sử dụng Set là khi bạn cần kết hợp nhiều đối tượng set bằng các phương thức kết hợp như union()difference(). Những phương thức này không có sẵn trong mảng.

3. Conclusion

Trong bài viết này chúng ta đã học được cách thức hoạt động của Map Set và khi nào nên sử dụng chúng trong code của bạn.

Nếu bạn thích bài viết này và muốn nâng cao kĩ năng JavaScript, tôi khuyên bạn nên xem cuốn sách mới của tôi Beginning Modern JavaScript tại đây

beginning-js-cover.png

Cuốn sách này được thiết kế đơn giản cho người mới bắt đầu và dễ tiếp cận với bất kì ai muốn học JavaScript. Nó cung cấp hướng dẫn step-by-step giúp bạn hiểu được cách sử dụng JavaScript để tạo ra một ứng dụng web động.

Đây là cam kết của tôi: Bạn sẽ thực sự cảm thấy mình hiểu rõ về JavaScript.

Hẹn gặp lại!


Tham khảo: https://www.freecodecamp.org/news/javascript-map-and-set-objects-explained


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí