diff --git a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md index e2147ccfa..e45deec63 100644 --- a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md +++ b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md @@ -1,43 +1,43 @@ -Let's store read messages in `WeakSet`: +Hãy lưu trữ tin nhắn đã đọc trong `WeakSet`: ```js run let messages = [ - {text: "Hello", from: "John"}, - {text: "How goes?", from: "John"}, - {text: "See you soon", from: "Alice"} + {text: "Xin chào", from: "John"}, + {text: "Tiến triển thế nào rồi?", from: "John"}, + {text: "Hẹn sớm gặp lại", from: "Alice"} ]; let readMessages = new WeakSet(); -// two messages have been read +// hai tin nhắn đã được đọc readMessages.add(messages[0]); readMessages.add(messages[1]); // readMessages has 2 elements -// ...let's read the first message again! +// ...hãy đọc lại tin nhắn đầu tiên! readMessages.add(messages[0]); -// readMessages still has 2 unique elements +// readMessages vẫn có 2 yếu tố độc nhất -// answer: was the message[0] read? +// trả lời: messages[0] đã được đọc chưa? alert("Read message 0: " + readMessages.has(messages[0])); // true messages.shift(); -// now readMessages has 1 element (technically memory may be cleaned later) +// bây giờ readMessages có 1 phần tử (về mặt kỹ thuật, bộ nhớ có thể được xóa sau) ``` -The `WeakSet` allows to store a set of messages and easily check for the existence of a message in it. +`WeakSet` cho phép lưu trữ một tập hợp các thông báo và dễ dàng kiểm tra sự tồn tại của một thông báo trong đó. -It cleans up itself automatically. The tradeoff is that we can't iterate over it, can't get "all read messages" from it directly. But we can do it by iterating over all messages and filtering those that are in the set. +Nó tự động dọn dẹp. Sự đánh đổi là chúng ta không thể lặp lại nó, không thể nhận trực tiếp "tất cả các tin nhắn đã đọc" từ nó. Nhưng chúng ta có thể làm điều đó bằng cách lặp lại tất cả các tin nhắn và lọc những tin nhắn có trong set. -Another, different solution could be to add a property like `message.isRead=true` to a message after it's read. As messages objects are managed by another code, that's generally discouraged, but we can use a symbolic property to avoid conflicts. +Một giải pháp khác, khác có thể là thêm thuộc tính như `message.isRead=true` vào tin nhắn sau khi tin nhắn được đọc. Vì các đối tượng thông báo được quản lý bởi một mã khác, điều đó thường không được khuyến khích, nhưng chúng ta có thể sử dụng một thuộc tính tượng trưng để tránh xung đột. -Like this: +Như thế này: ```js -// the symbolic property is only known to our code +// thuộc tính tượng trưng chỉ được biết đến với mã của chúng ta let isRead = Symbol("isRead"); messages[0][isRead] = true; ``` -Now third-party code probably won't see our extra property. +Bây giờ mã của bên thứ ba có thể sẽ không thấy thuộc tính bổ sung của chúng ta. -Although symbols allow to lower the probability of problems, using `WeakSet` is better from the architectural point of view. +Mặc dù các ký hiệu cho phép giảm xác suất xảy ra sự cố, nhưng sử dụng `WeakSet` sẽ tốt hơn từ quan điểm kiến trúc. diff --git a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md index fd31a891b..501f1929b 100644 --- a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md +++ b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md @@ -2,22 +2,22 @@ importance: 5 --- -# Store "unread" flags +# Lưu trữ cờ "chưa đọc" -There's an array of messages: +Có một array các tin nhắn: ```js let messages = [ - {text: "Hello", from: "John"}, - {text: "How goes?", from: "John"}, - {text: "See you soon", from: "Alice"} + {text: "Xin chào", from: "John"}, + {text: "Tiến triển thế nào rồi?", from: "John"}, + {text: "Hẹn sớm gặp lại", from: "Alice"} ]; ``` -Your code can access it, but the messages are managed by someone else's code. New messages are added, old ones are removed regularly by that code, and you don't know the exact moments when it happens. +Mã của bạn có thể truy cập nó, nhưng các tin nhắn được quản lý bởi mã của người khác. Các tin nhắn mới được thêm vào, các tin nhắn cũ bị mã đó xóa thường xuyên và bạn không biết chính xác thời điểm nó xảy ra. -Now, which data structure could you use to store information about whether the message "has been read"? The structure must be well-suited to give the answer "was it read?" for the given message object. +Bây giờ, bạn có thể sử dụng cấu trúc dữ liệu nào để lưu trữ thông tin về việc thư "đã được đọc" chưa? Cấu trúc phải phù hợp để đưa ra câu trả lời "đã đọc chưa?" cho đối tượng thông báo đã cho. -P.S. When a message is removed from `messages`, it should disappear from your structure as well. +Tái bút: Khi một tin nhắn bị xóa khỏi `messages`, nó cũng sẽ biến mất khỏi cấu trúc của bạn. -P.P.S. We shouldn't modify message objects, add our properties to them. As they are managed by someone else's code, that may lead to bad consequences. +Tái bút nữa: Chúng ta không nên sửa đổi các đối tượng tin nhắn, hãy thêm các thuộc tính của chúng ta vào chúng. Vì chúng được quản lý bởi mã của người khác, điều đó có thể dẫn đến hậu quả xấu. diff --git a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/solution.md b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/solution.md index 2af0547c1..3c2da9a01 100644 --- a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/solution.md +++ b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/solution.md @@ -1,15 +1,15 @@ -To store a date, we can use `WeakMap`: +Để lưu trữ một ngày, chúng ta có thể sử dụng `WeakMap`: ```js let messages = [ - {text: "Hello", from: "John"}, - {text: "How goes?", from: "John"}, - {text: "See you soon", from: "Alice"} + {text: "Xin chào", from: "John"}, + {text: "Tiến triển thế nào rồi?", from: "John"}, + {text: "Hẹn sớm gặp lại", from: "Alice"} ]; let readMap = new WeakMap(); readMap.set(messages[0], new Date(2017, 1, 1)); -// Date object we'll study later +// Đối tượng ngày chúng ta sẽ nghiên cứu sau ``` diff --git a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md index 8e341c184..4d68a1251 100644 --- a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md +++ b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md @@ -2,20 +2,20 @@ importance: 5 --- -# Store read dates +# Lưu trữ ngày đọc -There's an array of messages as in the [previous task](info:task/recipients-read). The situation is similar. +Có một array tin nhắn như trong [bài tập trước đó](info:task/recipients-read). Tình hình cũng tương tự. ```js let messages = [ - {text: "Hello", from: "John"}, - {text: "How goes?", from: "John"}, - {text: "See you soon", from: "Alice"} + {text: "Xin chào", from: "John"}, + {text: "Tiến triển thế nào rồi?", from: "John"}, + {text: "Hẹn sớm gặp lại", from: "Alice"} ]; ``` -The question now is: which data structure you'd suggest to store the information: "when the message was read?". +Câu hỏi bây giờ là: bạn muốn đề xuất cấu trúc dữ liệu nào để lưu trữ thông tin: "khi tin nhắn được đọc?". -In the previous task we only needed to store the "yes/no" fact. Now we need to store the date, and it should only remain in memory until the message is garbage collected. +Trong bài tập trước, chúng ta chỉ cần lưu trữ dữ kiện "có/không". Bây giờ chúng ta cần lưu trữ ngày tháng và nó chỉ nên lưu lại trong bộ nhớ cho đến khi thư được thu gom rác. -P.S. Dates can be stored as objects of built-in `Date` class, that we'll cover later. +Tái bút: Ngày tháng có thể được lưu trữ dưới dạng đối tượng của class `Date` tích hợp sẵn, mà chúng ta sẽ đề cập sau. diff --git a/1-js/05-data-types/08-weakmap-weakset/article.md b/1-js/05-data-types/08-weakmap-weakset/article.md index 5adbced20..86793e4ca 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -1,44 +1,46 @@ + # WeakMap and WeakSet -As we know from the chapter , JavaScript engine stores a value in memory while it is reachable (and can potentially be used). +Như chúng ta đã biết từ chương , JavaScript engine giữ một giá trị trong bộ nhớ khi giá trị đó "có thể truy cập được" và có khả năng được sử dụng. + +Ví dụ: -For instance: ```js let john = { name: "John" }; -// the object can be accessed, john is the reference to it +// đối tượng có thể được truy cập, john là tham chiếu đến nó -// overwrite the reference +// ghi đè tham chiếu john = null; *!* -// the object will be removed from memory +// đối tượng sẽ bị xóa khỏi bộ nhớ */!* ``` -Usually, properties of an object or elements of an array or another data structure are considered reachable and kept in memory while that data structure is in memory. +Thông thường, các thuộc tính của một đối tượng hoặc các phần tử của một array hoặc cấu trúc dữ liệu khác được coi là có thể truy cập và được lưu trong bộ nhớ trong khi cấu trúc dữ liệu đó nằm trong bộ nhớ. -For instance, if we put an object into an array, then while the array is alive, the object will be alive as well, even if there are no other references to it. +Chẳng hạn, nếu chúng ta đặt một đối tượng vào trong một array, thì trong khi array còn tồn tại, thì đối tượng đó cũng sẽ còn tồn tại, ngay cả khi không có tham chiếu nào khác đến nó. -Like this: +Như thế này: ```js let john = { name: "John" }; let array = [ john ]; -john = null; // overwrite the reference +john = null; // ghi đè tham chiếu *!* -// the object previously referenced by john is stored inside the array -// therefore it won't be garbage-collected -// we can get it as array[0] +// đối tượng được tham chiếu trước đó bởi john được lưu trữ bên trong array +// do đó nó sẽ không được thu gom rác +// chúng ta có thể lấy nó như array[0] */!* ``` -Similar to that, if we use an object as the key in a regular `Map`, then while the `Map` exists, that object exists as well. It occupies memory and may not be garbage collected. +Tương tự như vậy, nếu chúng ta sử dụng một đối tượng làm khóa trong `Map` thông thường, thì trong khi `Map` tồn tại, thì đối tượng đó cũng tồn tại. Nó chiếm bộ nhớ và có thể không được thu gom rác. -For instance: +Ví dụ: ```js let john = { name: "John" }; @@ -46,36 +48,36 @@ let john = { name: "John" }; let map = new Map(); map.set(john, "..."); -john = null; // overwrite the reference +john = null; // ghi đè tham chiếu *!* -// john is stored inside the map, -// we can get it by using map.keys() +// john được lưu trữ bên trong map, +// chúng ta có thể lấy nó bằng cách sử dụng map.keys() */!* ``` -`WeakMap` is fundamentally different in this aspect. It doesn't prevent garbage-collection of key objects. +[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) về cơ bản là khác nhau trong khía cạnh này. Nó không ngăn việc thu gom rác của các đối tượng chính. -Let's see what it means on examples. +Hãy xem ý nghĩa của nó trong các ví dụ. ## WeakMap -The first difference between `Map` and `WeakMap` is that keys must be objects, not primitive values: +Sự khác biệt đầu tiên giữa `Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) và [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) là các khóa phải là đối tượng, không phải giá trị nguyên hàm: ```js run let weakMap = new WeakMap(); let obj = {}; -weakMap.set(obj, "ok"); // works fine (object key) +weakMap.set(obj, "ok"); // hoạt động tốt (khóa đối tượng) *!* -// can't use a string as the key -weakMap.set("test", "Whoops"); // Error, because "test" is not an object +// không thể sử dụng một chuỗi làm khóa +weakMap.set("test", "Whoops"); // Error, bởi vì "test" không phải là một đối tượng */!* ``` -Now, if we use an object as the key in it, and there are no other references to that object -- it will be removed from memory (and from the map) automatically. +Bây giờ, nếu chúng ta sử dụng một đối tượng làm khóa trong đó và không có tham chiếu nào khác đến đối tượng đó -- nó sẽ tự động bị xóa khỏi bộ nhớ (và khỏi map). ```js let john = { name: "John" }; @@ -83,131 +85,132 @@ let john = { name: "John" }; let weakMap = new WeakMap(); weakMap.set(john, "..."); -john = null; // overwrite the reference +john = null; // ghi đè tham chiếu -// john is removed from memory! +// john bị xóa khỏi bộ nhớ! ``` -Compare it with the regular `Map` example above. Now if `john` only exists as the key of `WeakMap` -- it will be automatically deleted from the map (and memory). +So sánh nó với ví dụ `Map` thông thường ở trên. Bây giờ nếu `john` chỉ tồn tại dưới dạng khóa của `WeakMap` -- nó sẽ tự động bị xóa khỏi map (và bộ nhớ). -`WeakMap` does not support iteration and methods `keys()`, `values()`, `entries()`, so there's no way to get all keys or values from it. +`WeakMap` không hỗ trợ phép lặp và các phương thức `keys()`, `values()`, `entries()`, vì vậy không có cách nào để lấy tất cả các khóa hoặc giá trị từ nó. -`WeakMap` has only the following methods: +`WeakMap` chỉ có các phương thức sau: -- `weakMap.get(key)` -- `weakMap.set(key, value)` -- `weakMap.delete(key)` -- `weakMap.has(key)` +- [`weakMap.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/set) +- [`weakMap.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/get) +- [`weakMap.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/delete) +- [`weakMap.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/has) -Why such a limitation? That's for technical reasons. If an object has lost all other references (like `john` in the code above), then it is to be garbage-collected automatically. But technically it's not exactly specified *when the cleanup happens*. +Tại sao lại có hạn chế như vậy? Đó là vì lý do kỹ thuật. Nếu một đối tượng bị mất tất cả các tham chiếu khác (như `john` trong mã ở trên), thì đối tượng đó sẽ được thu gom rác tự động. Nhưng về mặt kỹ thuật, nó không được chỉ định chính xác *khi quá trình thu gom diễn ra*. -The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically, the current element count of a `WeakMap` is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access all keys/values are not supported. +JavaScript engine quyết định điều đó. Nó có thể chọn thực hiện dọn dẹp bộ nhớ ngay lập tức hoặc đợi và thực hiện dọn dẹp sau khi có nhiều thao tác xóa hơn. Vì vậy, về mặt kỹ thuật, số phần tử hiện tại của `WeakMap` không được biết. Engine có thể đã dọn nó hoặc chưa, hoặc đã làm một phần. Vì lý do đó, các phương thức truy cập tất cả khóa/giá trị không được hỗ trợ. -Now, where do we need such a data structure? +Bây giờ, chúng ta cần một cấu trúc dữ liệu như vậy ở đâu? -## Use case: additional data +## Trường hợp sử dụng: dữ liệu bổ sung -The main area of application for `WeakMap` is an *additional data storage*. +Lĩnh vực ứng dụng chính của `WeakMap` là *lưu trữ dữ liệu bổ sung*. -If we're working with an object that "belongs" to another code, maybe even a third-party library, and would like to store some data associated with it, that should only exist while the object is alive - then `WeakMap` is exactly what's needed. +Nếu chúng ta đang làm việc với một đối tượng "thuộc về" một mã khác, thậm chí có thể là thư viện của bên thứ ba và muốn lưu trữ một số dữ liệu được liên kết với nó, dữ liệu đó chỉ tồn tại khi đối tượng còn tồn tại - thì `WeakMap` là chính xác những gì cần thiết. -We put the data to a `WeakMap`, using the object as the key, and when the object is garbage collected, that data will automatically disappear as well. +Chúng ta đặt dữ liệu vào `WeakMap`, sử dụng đối tượng làm khóa và khi đối tượng được thu gom rác, dữ liệu đó cũng sẽ tự động biến mất. ```js -weakMap.set(john, "secret documents"); -// if john dies, secret documents will be destroyed automatically +weakMap.set(john, "tài liệu bí mật"); +// nếu john chết, tài liệu bí mật sẽ tự động bị hủy ``` -Let's look at an example. +Hãy xem một ví dụ. -For instance, we have code that keeps a visit count for users. The information is stored in a map: a user object is the key and the visit count is the value. When a user leaves (its object gets garbage collected), we don't want to store their visit count anymore. +Chẳng hạn, chúng ta có mã giữ số lượt truy cập cho người dùng. Thông tin được lưu trữ trong map: đối tượng người dùng là khóa và số lượt truy cập là giá trị. Khi người dùng rời đi (đối tượng của nó được thu gom rác), chúng ta không muốn lưu trữ số lượt truy cập của họ nữa. -Here's an example of a counting function with `Map`: +Đây là một ví dụ về hàm đếm với `Map`: ```js // 📁 visitsCount.js -let visitsCountMap = new Map(); // map: user => visits count +let visitsCountMap = new Map(); // map: người dùng => số lượt truy cập -// increase the visits count +// tăng số lượt truy cập function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); } ``` -And here's another part of the code, maybe another file using it: +Và đây là một phần khác của mã, có thể là một tệp khác sử dụng nó: ```js // 📁 main.js let john = { name: "John" }; -countUser(john); // count his visits +countUser(john); // đếm số lượt truy cập của anh ấy -// later john leaves us +// sau đó john rời khỏi đây john = null; ``` -Now, `john` object should be garbage collected, but remains in memory, as it's a key in `visitsCountMap`. +Bây giờ, đối tượng `john` nên được thu gom rác, nhưng vẫn còn trong bộ nhớ, vì nó là một khóa trong `visitsCountMap`. -We need to clean `visitsCountMap` when we remove users, otherwise it will grow in memory indefinitely. Such cleaning can become a tedious task in complex architectures. +Chúng ta cần xóa `visitsCountMap` khi chúng ta xóa người dùng, nếu không nó sẽ phát triển trong bộ nhớ vô thời hạn. Việc làm sạch như vậy có thể trở thành một công việc tẻ nhạt trong các kiến trúc phức tạp. -We can avoid it by switching to `WeakMap` instead: +Thay vào đó, chúng ta có thể tránh nó bằng cách chuyển sang `WeakMap`: ```js // 📁 visitsCount.js -let visitsCountMap = new WeakMap(); // weakmap: user => visits count +let visitsCountMap = new WeakMap(); // weakmap: người dùng => số lượt truy cập -// increase the visits count +// tăng số lượt truy cập function countUser(user) { let count = visitsCountMap.get(user) || 0; visitsCountMap.set(user, count + 1); } ``` -Now we don't have to clean `visitsCountMap`. After `john` object becomes unreachable, by all means except as a key of `WeakMap`, it gets removed from memory, along with the information by that key from `WeakMap`. +Bây giờ chúng ta không phải xóa `visitsCountMap`. Sau khi không thể truy cập đối tượng `john`, bằng mọi cách, ngoại trừ dưới dạng một khóa của `WeakMap`, nó sẽ bị xóa khỏi bộ nhớ, cùng với thông tin theo khóa đó từ `WeakMap`. -## Use case: caching +## Trường hợp sử dụng: bộ nhớ đệm -Another common example is caching. We can store ("cache") results from a function, so that future calls on the same object can reuse it. +Một ví dụ phổ biến khác là bộ nhớ đệm. Chúng ta có thể lưu trữ ("bộ nhớ đệm") kết quả từ một hàm, để các cuộc gọi trong tương lai trên cùng một đối tượng có thể sử dụng lại nó. -To achieve that, we can use `Map` (not optimal scenario): +Để đạt được điều đó, chúng ta có thể sử dụng `Map` (kịch bản không tối ưu): ```js run // 📁 cache.js let cache = new Map(); -// calculate and remember the result +// tính toán và ghi nhớ kết quả function process(obj) { if (!cache.has(obj)) { - let result = /* calculations of the result for */ obj; + let result = /* tính toán kết quả cho */ obj; cache.set(obj, result); + return result; } return cache.get(obj); } *!* -// Now we use process() in another file: +// Bây giờ chúng ta sử dụng process() trong một tệp khác: */!* // 📁 main.js -let obj = {/* let's say we have an object */}; +let obj = {/* giả sử chúng ta có một đối tượng */}; -let result1 = process(obj); // calculated +let result1 = process(obj); // tính toán -// ...later, from another place of the code... -let result2 = process(obj); // remembered result taken from cache +// ...sau đó, từ một nơi khác của mã ... +let result2 = process(obj); // ghi nhớ kết quả lấy từ bộ nhớ đệm -// ...later, when the object is not needed any more: +// ...sau này, khi đối tượng không còn cần thiết nữa: obj = null; -alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!) +alert(cache.size); // 1 (Ôi! Đối tượng vẫn còn trong bộ đệm, chiếm bộ nhớ!) ``` -For multiple calls of `process(obj)` with the same object, it only calculates the result the first time, and then just takes it from `cache`. The downside is that we need to clean `cache` when the object is not needed any more. +Đối với nhiều lệnh gọi `process(obj)` với cùng một đối tượng, nó chỉ tính toán kết quả lần đầu tiên và sau đó chỉ lấy kết quả từ `cache`. Nhược điểm là chúng ta cần dọn `cache` khi đối tượng không còn cần thiết nữa. -If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected. +Nếu chúng ta thay thế `Map` bằng `WeakMap` thì vấn đề này sẽ biến mất. Kết quả được lưu trong bộ nhớ đệm sẽ tự động bị xóa khỏi bộ nhớ sau khi đối tượng được thu gom rác. ```js run // 📁 cache.js @@ -215,12 +218,13 @@ If we replace `Map` with `WeakMap`, then this problem disappears. The cached res let cache = new WeakMap(); */!* -// calculate and remember the result +// tính toán và ghi nhớ kết quả function process(obj) { if (!cache.has(obj)) { - let result = /* calculate the result for */ obj; + let result = /* tính toán kết quả cho */ obj; cache.set(obj, result); + return result; } return cache.get(obj); @@ -232,25 +236,25 @@ let obj = {/* some object */}; let result1 = process(obj); let result2 = process(obj); -// ...later, when the object is not needed any more: +// ...sau đó, khi đối tượng không còn cần thiết nữa: obj = null; -// Can't get cache.size, as it's a WeakMap, -// but it's 0 or soon be 0 -// When obj gets garbage collected, cached data will be removed as well +// Không thể lấy cache.size, vì nó là một WeakMap, +// nhưng nó là 0 hoặc sớm là 0 +// Khi obj được thu gom rác, dữ liệu được lưu trong bộ nhớ đệm cũng sẽ bị xóa ``` ## WeakSet -`WeakSet` behaves similarly: +[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) hoạt động tương tự: -- It is analogous to `Set`, but we may only add objects to `WeakSet` (not primitives). -- An object exists in the set while it is reachable from somewhere else. -- Like `Set`, it supports `add`, `has` and `delete`, but not `size`, `keys()` and no iterations. +- Tương tự như `Set`, nhưng chúng ta chỉ có thể thêm các đối tượng vào `WeakSet` (không phải các đối tượng nguyên hàm). +- Một đối tượng tồn tại trong set trong khi nó có thể truy cập được từ một nơi khác. +- Giống như `Set`, nó hỗ trợ [`add`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/add), [`has`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/has) và [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/delete), nhưng không hỗ trợ `size`, `keys()` và không lặp lại. -Being "weak", it also serves as additional storage. But not for arbitrary data, rather for "yes/no" facts. A membership in `WeakSet` may mean something about the object. +Là "yếu", nó cũng đóng vai trò là bộ nhớ bổ sung. Nhưng không phải cho dữ liệu tùy ý, mà là cho các dữ kiện "có/không". Tư cách thành viên trong `WeakSet` có thể có ý nghĩa gì đó về đối tượng. -For instance, we can add users to `WeakSet` to keep track of those who visited our site: +Chẳng hạn, chúng ta có thể thêm người dùng vào `WeakSet` để theo dõi những người đã truy cập trang web của chúng ta: ```js run let visitedSet = new WeakSet(); @@ -259,33 +263,33 @@ let john = { name: "John" }; let pete = { name: "Pete" }; let mary = { name: "Mary" }; -visitedSet.add(john); // John visited us -visitedSet.add(pete); // Then Pete -visitedSet.add(john); // John again +visitedSet.add(john); // John đến thăm chúng ta +visitedSet.add(pete); // Sau đó Pete +visitedSet.add(john); // Lại là John -// visitedSet has 2 users now +// visitedSet hiện có 2 người dùng -// check if John visited? +// kiểm tra xem John có đến thăm không? alert(visitedSet.has(john)); // true -// check if Mary visited? +// kiểm tra xem Mary có đến thăm không? alert(visitedSet.has(mary)); // false john = null; -// visitedSet will be cleaned automatically +// visitedSet sẽ được dọn tự động ``` -The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterations, and the inability to get all current content. That may appear inconvenient, but does not prevent `WeakMap/WeakSet` from doing their main job -- be an "additional" storage of data for objects which are stored/managed at another place. +Hạn chế đáng chú ý nhất của `WeakMap` và `WeakSet` là không có phép lặp và không thể lấy tất cả nội dung hiện tại. Điều đó có vẻ bất tiện, nhưng không ngăn cản `WeakMap/WeakSet` thực hiện công việc chính của chúng -- trở thành nơi lưu trữ dữ liệu "bổ sung" cho các đối tượng được lưu trữ/quản lý ở một nơi khác. -## Summary +## Tóm tắt -`WeakMap` is `Map`-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means. +[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) là bộ sưu tập giống như `Map` chỉ cho phép các đối tượng làm khóa và loại bỏ chúng cùng với giá trị được liên kết sau khi chúng không thể truy cập được bằng các phương tiện khác. -`WeakSet` is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means. +[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) là bộ sưu tập giống như `Set` chỉ lưu trữ các đối tượng và loại bỏ chúng khi chúng không thể truy cập được bằng các cách khác. -Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector. +Ưu điểm chính của chúng là chúng có tham chiếu yếu đến các đối tượng, vì vậy chúng có thể dễ dàng bị loại bỏ bởi trình thu gom rác. -That comes at the cost of not having support for `clear`, `size`, `keys`, `values`... +Điều đó phải trả giá bằng việc không hỗ trợ `clear`, `size`, `keys`, `values`... -`WeakMap` and `WeakSet` are used as "secondary" data structures in addition to the "primary" object storage. Once the object is removed from the primary storage, if it is only found as the key of `WeakMap` or in a `WeakSet`, it will be cleaned up automatically. +`WeakMap` và `WeakSet` được sử dụng làm cấu trúc dữ liệu "phụ" ngoài bộ lưu trữ đối tượng "chính". Sau khi đối tượng bị xóa khỏi bộ lưu trữ chính, nếu đối tượng chỉ được tìm thấy dưới dạng khóa của `WeakMap` hoặc trong `WeakSet`, thì đối tượng đó sẽ tự động được dọn.