From a3e54cfc3335689b19757f37f164867490f96398 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:04:30 +0700 Subject: [PATCH 01/12] Update article.md --- .../08-weakmap-weakset/article.md | 176 +++++++++--------- 1 file changed, 88 insertions(+), 88 deletions(-) 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..d2398495c 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,44 @@ # 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 lưu trữ một giá trị trong bộ nhớ trong khi nó có thể truy cập được (và có thể được sử dụng). -For instance: +Ví dụ: ```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 +46,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` 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` và `WeakMap` là các khóa phải là đối tượng, không phải giá trị nguyên thủy: ```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,100 +83,100 @@ 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)` -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 dọn dẹp 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ể đã làm sạch 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 +// nếu john chết, các 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 chúng tôi 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ộ đệ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; @@ -188,26 +188,26 @@ function process(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 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 dẹp `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,7 +215,7 @@ 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; @@ -232,25 +232,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` 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 thủy). +- 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`, `has` và `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 +259,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 dẹp 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` 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` 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 sạch. From 1db43c841ff623546888eebf55175f2342ca6d10 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:06:29 +0700 Subject: [PATCH 02/12] Update task.md --- .../01-recipients-read/task.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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..387db8d23 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 `tin nhắn`, 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. From 88a3971c885fa526d05818b039b45ef63cdf6597 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:08:54 +0700 Subject: [PATCH 03/12] Update solution.md --- .../01-recipients-read/solution.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) 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..00370d886 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 -// 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 tập hợp. -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 thư sau khi thư đượ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. From e4471175f6cebb837cb04e5d570815eec1da17ca Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:10:28 +0700 Subject: [PATCH 04/12] Update task.md --- .../02-recipients-when-read/task.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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..9f39b06da 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 [nhiệm vụ 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 tác vụ 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 lớp `Date` tích hợp sẵn, mà chúng ta sẽ đề cập sau. From d65a49566144d461f824c5e2e0ae54529b6a8d09 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:11:22 +0700 Subject: [PATCH 05/12] Update solution.md --- .../02-recipients-when-read/solution.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 ``` From c63088888d8511b15f30590793d5fff94b02934b Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 7 Mar 2023 20:22:25 +0700 Subject: [PATCH 06/12] Update solution.md --- .../08-weakmap-weakset/01-recipients-read/solution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 00370d886..1deeb955e 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 @@ -16,7 +16,7 @@ readMessages.add(messages[1]); // ...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ố duy nhất // trả lời: messages[0] đã được đọc chưa? alert("Read message 0: " + readMessages.has(messages[0])); // true @@ -40,4 +40,4 @@ messages[0][isRead] = true; 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 biểu tượng 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 kiến trúc. From eb01230db8f8004b5ff929512106d55d1c4adfb4 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:49:18 +0700 Subject: [PATCH 07/12] Update solution.md --- .../08-weakmap-weakset/01-recipients-read/solution.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 1deeb955e..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 @@ -16,7 +16,7 @@ readMessages.add(messages[1]); // ...hãy đọc lại tin nhắn đầu tiên! readMessages.add(messages[0]); -// readMessages vẫn có 2 yếu tố duy nhất +// readMessages vẫn có 2 yếu tố độc nhất // trả lời: messages[0] đã được đọc chưa? alert("Read message 0: " + readMessages.has(messages[0])); // true @@ -27,9 +27,9 @@ messages.shift(); `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 đó. -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 tập hợp. +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. -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 thư sau khi thư đượ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. +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. Như thế này: ```js @@ -40,4 +40,4 @@ messages[0][isRead] = true; 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. -Mặc dù các biểu tượng 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 kiến trúc. +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. From df920639860d12a14e8695e135ce0db0d154d9e2 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:50:05 +0700 Subject: [PATCH 08/12] Update task.md --- .../05-data-types/08-weakmap-weakset/01-recipients-read/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 387db8d23..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 @@ -18,6 +18,6 @@ Mã của bạn có thể truy cập nó, nhưng các tin nhắn được quản 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. -Tái bút: Khi một tin nhắn bị xóa khỏi `tin nhắn`, nó cũng sẽ biến mất khỏi cấu trúc của bạn. +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. 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. From bb6fd89d2b3e7f454227ca8ea1f0ff7c5f3b013f Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:50:41 +0700 Subject: [PATCH 09/12] Update task.md --- .../08-weakmap-weakset/02-recipients-when-read/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9f39b06da..99d6a99ce 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 @@ -4,7 +4,7 @@ importance: 5 # Lưu trữ ngày đọc -Có một array tin nhắn như trong [nhiệm vụ trước đó](info:task/recipients-read). Tình hình cũng tương tự. +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 = [ From e7a07471003701372fa17972b9af7453188167c5 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:51:27 +0700 Subject: [PATCH 10/12] Update task.md --- .../08-weakmap-weakset/02-recipients-when-read/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 99d6a99ce..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 @@ -16,6 +16,6 @@ let messages = [ 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?". -Trong tác vụ 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. +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. -Tái bút: Ngày tháng có thể được lưu trữ dưới dạng đối tượng của lớp `Date` tích hợp sẵn, mà chúng ta sẽ đề cập sau. +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. From 813e5b541c442cfa92d13e9557fe9acdc743ca53 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:33:04 +0700 Subject: [PATCH 11/12] some fixes --- .../08-weakmap-weakset/article.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) 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 d2398495c..38b718c36 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -60,7 +60,7 @@ Hãy xem ý nghĩa của nó trong các ví dụ. ## WeakMap -Sự khác biệt đầu tiên giữa `Map` và `WeakMap` là các khóa phải là đối tượng, không phải giá trị nguyên thủy: +Sự khác biệt đầu tiên giữa `Map` và `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(); @@ -99,9 +99,9 @@ So sánh nó với ví dụ `Map` thông thường ở trên. Bây giờ nếu ` - `weakMap.delete(key)` - `weakMap.has(key)` -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 dọn dẹp diễn ra*. +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*. -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ể đã làm sạch 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ợ. +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ợ. Bây giờ, chúng ta cần một cấu trúc dữ liệu như vậy ở đâu? @@ -114,8 +114,8 @@ Nếu chúng ta đang làm việc với một đối tượng "thuộc về" m 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"); -// nếu john chết, các tài liệu bí mật sẽ tự động bị hủy +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 ``` Hãy xem một ví dụ. @@ -143,7 +143,7 @@ let john = { name: "John" }; countUser(john); // đếm số lượt truy cập của anh ấy -// sau đó john rời khỏi chúng tôi +// sau đó john rời khỏi đây john = null; ``` @@ -168,7 +168,7 @@ Bây giờ chúng ta không phải xóa `visitsCountMap`. Sau khi không thể t ## Trường hợp sử dụng: bộ nhớ đệm -Một ví dụ phổ biến khác là bộ nhớ đệm. Chúng ta có thể lưu trữ ("bộ đệ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ó. +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ó. Để đạt được điều đó, chúng ta có thể sử dụng `Map` (kịch bản không tối ưu): @@ -179,7 +179,7 @@ let cache = new Map(); // 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); } @@ -192,7 +192,7 @@ function process(obj) { */!* // 📁 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); // tính toán @@ -205,7 +205,7 @@ obj = null; alert(cache.size); // 1 (Ôi! Đối tượng vẫn còn trong bộ đệm, chiếm bộ nhớ!) ``` -Đố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 dẹp `cache` khi đối tượng không còn cần thiết nữa. +Đố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. 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. @@ -218,7 +218,7 @@ let cache = new WeakMap(); // 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); } @@ -244,7 +244,7 @@ obj = null; `WeakSet` hoạt động tương tự: -- 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 thủy). +- 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`, `has` và `delete`, nhưng không hỗ trợ `size`, `keys()` và không lặp lại. @@ -273,7 +273,7 @@ alert(visitedSet.has(mary)); // false john = null; -// visitedSet sẽ được dọn dẹp tự động +// visitedSet sẽ được dọn tự động ``` 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. @@ -288,4 +288,4 @@ Hạn chế đáng chú ý nhất của `WeakMap` và `WeakSet` là không có p Điều đó phải trả giá bằng việc không hỗ trợ `clear`, `size`, `keys`, `values`... -`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 sạch. +`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. From 1a0b82fb3b451ec06d80ce17d4280b0483e126e9 Mon Sep 17 00:00:00 2001 From: I_am_Vietnam <91591390+ImVietnam@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:57:53 +0700 Subject: [PATCH 12/12] sync with en version --- .../08-weakmap-weakset/article.md | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) 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 38b718c36..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,8 +1,10 @@ + # WeakMap and WeakSet -Như chúng ta đã biết từ chương , JavaScript engine lưu trữ một giá trị trong bộ nhớ trong khi nó có thể truy cập được (và có thể được sử dụng). +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ụ: + ```js let john = { name: "John" }; @@ -54,13 +56,13 @@ john = null; // ghi đè tham chiếu */!* ``` -`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. +[`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. Hãy xem ý nghĩa của nó trong các ví dụ. ## WeakMap -Sự khác biệt đầu tiên giữa `Map` và `WeakMap` là các khóa phải là đối tượng, không phải giá trị nguyên hàm: +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(); @@ -94,10 +96,10 @@ So sánh nó với ví dụ `Map` thông thường ở trên. Bây giờ nếu ` `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) 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*. @@ -182,6 +184,7 @@ function process(obj) { let result = /* tính toán kết quả cho */ obj; cache.set(obj, result); + return result; } return cache.get(obj); @@ -221,6 +224,7 @@ function process(obj) { let result = /* tính toán kết quả cho */ obj; cache.set(obj, result); + return result; } return cache.get(obj); @@ -242,11 +246,11 @@ obj = null; ## WeakSet -`WeakSet` hoạt động tương tự: +[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) hoạt động tương tự: - 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`, `has` và `delete`, nhưng không hỗ trợ `size`, `keys()` và không lặp lại. +- 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. 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. @@ -280,9 +284,9 @@ Hạn chế đáng chú ý nhất của `WeakMap` và `WeakSet` là không có p ## Tóm tắt -`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. +[`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` 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. +[`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. Ư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.