Keyed collections

Bản dịch này chưa hoàn thành. Xin hãy giúp dịch bài viết này từ tiếng Anh

Chương này sẽ giới thiệu về bộ sưu tập dữ liệu được sắp xếp theo key; Map và Set objects chứa các phần tử có thể được lặp lại theo thứ tự được thêm vào.

Maps

Map object

ECMAScript 2015 giới thiệu một cấu trúc dữ liệu mới để ánh xạ giá trị thành giá trị. Một đối tượng Map là một ánh xạ đơn giản key/value và có thể lặp lại các phần tử theo thứ tự thêm vào.

Đoạn code bên dưới sẽ thể hiện các thao tác cơ bản với Map. Xem thêm Map để có thêm nhiều ví dụ và toàn bộ API. Bạn có thể sử dụng một vòng lặp for...of để trả về một mảng của [key, value] trong mỗi lần lặp.

let sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
sayings.set('elephant', 'toot');
sayings.size; // 3
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false

for (let [key, value] of sayings) {
  console.log(key + ' goes ' + value);
}
// "cat goes meow"
// "elephant goes toot"

sayings.clear();
sayings.size; // 0 

Object and Map compared

Thông thường, objects được sử dụng để ánh xạ string thành value. Objects cũng cho phép bạn đặt key thành values, truy xuất các value, xóa các key, và kiểm tra xe có dữ liệu nào được lưu trữ trong một key. Tuy nhiên Map objects có một vài lợi thế hơn giúp chúng tốt hơn trong việc ánh xạ.

  • Các key trong một ObjectStrings hoặc Symbols, trong khi chúng có thể là bất kỳ giá trị nào trong một Map.
  • Bạn có thể lấy được size của một Map dễ dàng, trong khi bạn sẽ phải xử lý thủ công để lấy được kích thước của một Object.
  • Vòng lặp của các ánh xạ sẽ theo thứ tự được thêm vào của  các phần tử.
  • Một Object có một prototype, vì thế có các giá trị mặc định của key trong ánh xạ. (Điều này có thể bỏ qua bằng cách sử dụng map = Object.create(null).)

Ba mẹo dưới đây có thể giúp bạn quyết định khi nào thì sử dụng Map hoặc Object:

  • Sử dụng các object khi các key không được xác định cho đến khi chạy, và khi tất cả các key có cùng kiểu và tất cả các value cũng cùng kiểu.
  • Sử dụng các map nếu cần lưu trữ các giá trị có kiểu nguyên thủy làm key vì các object coi mỗi key là một string cho dù nó là một giá trị số, boolean hoặc bất kỳ giá trị có kiểu nguyên thủy nào.
  • Sử dụng các object khi có logic hoạt động trên các yếu tố riêng lẻ.

WeakMap object

Đối tượng WeakMap là một bộ sưu tập của cặp key/value trong đó các key chỉ là các đối tượng và các value có thể là bất kỳ giá trị nào. Tham chiếu đối tượng trong các key được giữ yếu ớt (weakly), có nghĩa là chúng là mục tiêu của garbage collection (GC) nếu không có tham chiếu nào khác đến đối tượng nữa. Các WeakMap API giống với các Map API.

Một điểm khác biệt so với các Map objects là các key của WeakMap không đếm được (tức là không có phương thức nào cung cấp cho bạn danh sách các key). Nếu có, danh sách key sẽ phụ thuộc vào trạng thái của garbage collection, đưa ra tính không xác định.

Một số thông tin và ví dụ khác, xem tại "Why WeakMap?" trong tài liệu tham khảo WeakMap.

Một trường hợp sử dụng các WeakMap objec là lưu trữ dữ liệu riêng tư cho một đối tượng hoặc ấn chi tiết thực hiện. Ví dụ sau đây từ bài đăng trên blog của Nick Fitzgerald's  "Hiding Implementation Details with ECMAScript 6 WeakMaps". Các dữ liệu và phương thức riêng bên trong object sẽ được lưu trữ trong đối tượng privates. Tất cả các instance và prototype lộ ra được công khai; mọi thứ khác không thể truy cập từ bên ngoài bởi vì privates không được xuất từ mô-đun.

const privates = new WeakMap();

function Public() {
  const me = {
    // Private data goes here
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // Do stuff with private data in `me`...
};

module.exports = Public;

Sets

Set object

Các Set object là bộ sưu tập các giá trị. Bạn có thể lặp các phần tử theo thứ tự được thêm vào. Một giá trị trong một Set chỉ có thể xuất hiện một lần; nó là duy nhất trong Set.

Đoạn code dưới đây là các thao tác cơ bản với Set. Xem thêm tại tài liệu tham khảo Set để có thêm nhiều ví dụ và toàn bộ các API.

let mySet = new Set();
mySet.add(1);
mySet.add('some text');
mySet.add('foo');

mySet.has(1); // true
mySet.delete('foo');
mySet.size; // 2

for (let item of mySet) console.log(item);
// 1
// "some text"

Converting between Array and Set

Bạn có thể tạo một Array từ một Set bằng cách sử dụng Array.from hoặc spread operator. Ngoài ra, hàm khởi tạo Set cho phép chuyển đổi một Array theo một hướng khác.

Note: Hãy nhớ rằng các Set object lưu trữ các giá trị duy nhất—vì thế bất kỳ phần tử nào trùng lặp trong Array sẽ bị loại bỏ khi chuyển đổi!

Array.from(mySet);
[...mySet2];

mySet2 = new Set([1, 2, 3, 4]);

Array and Set compared

Thông thường, một tập hợp các phần tử được lưu trữ trong mảng trong JavaScript trong nhiều tính huống. Tuy nhiên, Set object có một vài điểm lợi thế sau:

  • Xóa bỏ các phẩn tử trong mảng theo giá trị (arr.splice(arr.indexOf(val), 1)) rất chậm.
  • Set object cho phép bạn xóa bỏ các phần tử theo giá trị của chúng. Trong khi đó một mảng, bạn sẽ phải dùng phương thức splice dựa theo index của phần tử.
  • Giá trị NaN không thể được tìm thất với indexOf trong một mảng.
  • Các Set object lưu trữ các giá trị duy nhất. Bạn không cần phải thao tác thủ công để theo dõi các giá trị bị trùng lặp.

WeakSet object

Các WeakSet object là bộ sưu tập các đối tượng. Một đối tượng trong WeakSet chỉ xuất hiện một lần. Nó là duy nhất trong bộ sưu tập WeakSet, và các đối tượng đó không thể đếm được.

Những điểm khác biệt chính so với Set object:

  • Khác với Sets, WeakSets là bộ sưu tập các đối tượng và không phải bất kỳ giá trị của bất kỳ kiểu nào. 
  • WeakSet là yếu ớt (weak): Tham chiếu tới đối tượng trong bộ sưu tập được tổ chức yếu ớt (weakly). Nếu không có tham chiếu nào khác tới đối tượng được lưu trữ trong WeakSet, chúng có thể bị thu thập bởi garbage collected. Điều này có nghĩa là không có danh sách các đối tượng đang được lưu trữ trong bộ sưu tập. WeakSets không thể đếm được.

Các trường hợp sử dụng các  WeakSet object bị hạn chế. Chúng sẽ không rò rỉ bộ nhớ, vì thế nó có thể an toàn khi sử dụng các phần tử DOM làm khóa và đánh dấu chúng cho mục đích theo dõi.

Key and value equality of Map and Set

So sánh bằng nhau của các key của các Map object và value của các Set object dựa trên "same-value-zero algorithm":

  • So sánh bằng nhau làm việc giống như so sánh bằng toán tử ===.
  • -0+0 được coi là bằng nhau.
  • NaN được coi là bằng chính nó (trái với ===).