Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Let's store read messages in `WeakSet`:
讓我們將已讀的訊息存在 `WeakSet` 中:

```js run
let messages = [
Expand All @@ -9,35 +9,35 @@ let messages = [

let readMessages = new WeakSet();

// two messages have been read
// 兩個訊息已經被讀取了
readMessages.add(messages[0]);
readMessages.add(messages[1]);
// readMessages has 2 elements
// readMessages 有兩個元素

// ...let's read the first message again!
// ...讓我們再次讀取第一個訊息!
readMessages.add(messages[0]);
// readMessages still has 2 unique elements
// readMessages 依然有兩個唯一的元素

// answer: was the message[0] read?
// 回答:message[0] 是否已被讀取?
alert("Read message 0: " + readMessages.has(messages[0])); // true

messages.shift();
// now readMessages has 1 element (technically memory may be cleaned later)
// 現在 readMessages 只有一個元素(技術上來說,記憶體可能會在稍後才被清理)
```

The `WeakSet` allows to store a set of messages and easily check for the existance of a message in it.
`WeakSet` 允許儲存訊息的集合,且能簡單地檢查一個訊息是否存在於集合內。

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.
它會自動清理自己,但代價是我們不能夠迭代它,無法直接取得 "所有已讀訊息"。但我們可以透過迭代所有訊息,並過濾掉那些存在集合中的訊息來達到同樣目的。

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.
另外一個不同的解法可以是當訊息被讀取後,增加一個屬性,像 `message.isRead=true` 到訊息中。當訊息物件被其他程式碼管理時,這樣的作法一般是不建議的,但我們可以用 Symbol 屬性來避免衝突。

Like this:
像這樣:
```js
// the symbolic property is only known to our code
// Symbol 屬性只會在我們的程式碼中被認得
let isRead = Symbol("isRead");
messages[0][isRead] = true;
```

Now third-party code probably won't see our extra property.
現在第三方程式碼可能不會看到我們的額外屬性。

Although symbols allow to lower the probability of problems, using `WeakSet` is better from the architectural point of view.
雖然 Symbol 可以降低問題發生的機率,但從架構的觀點來看,使用 `WeakSet` 是比較好的。
12 changes: 6 additions & 6 deletions 1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# Store "unread" flags
# 儲存 "未讀" 旗標

There's an array of messages:
有一個訊息陣列:

```js
let messages = [
Expand All @@ -14,10 +14,10 @@ let messages = [
];
```

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.
你的程式碼可以存取它,但這些訊息是被其他人的程式碼管理著。該程式碼定期地加入新訊息,移除舊訊息,而你不知道確切何時會發生這些變化。

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.
現在,哪一種資料結構你可以用來儲存訊息 "是否已被讀取"?該結構必須非常合適地針對給定的訊息物件給出 "它被讀取了嗎" 的答案。

P.S. When a message is removed from `messages`, it should disappear from your structure as well.
註:當一個訊息從 `messages` 中被移除時,它也應該要從你的結構中消失。

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.
註 2:我們不應該更動訊息物件,或是增加我們自己的屬性到上面。因為它們被其他人的程式碼管理著,這樣做可能會導致壞的後果。
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

To store a date, we can use `WeakMap`:
要儲存日期,我們可以用 `WeakMap`

```js
let messages = [
Expand All @@ -11,5 +11,5 @@ let messages = [
let readMap = new WeakMap();

readMap.set(messages[0], new Date(2017, 1, 1));
// Date object we'll study later
// 我們之後會讀到日期物件
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 5

---

# Store read dates
# 儲存已讀日期

There's an array of messages as in the [previous task](info:task/recipients-read). The situation is similar.
與 [上一個課題](info:task/recipients-read) 類似的情境,存在一個訊息陣列。

```js
let messages = [
Expand All @@ -14,8 +14,8 @@ let messages = [
];
```

The question now is: which data structure you'd suggest to store the information: "when the message was read?".
現在的問題是:你建議用哪個資料結構來儲存這樣的資訊:"訊息在何時被讀取?"。

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.
在前一個任務中,我們只需要儲存 "是/否" 的事實陳述,現在我們需要儲存日期,且它應該只能在訊息被垃圾回收前存在。

P.S. Dates can be stored as objects of built-in `Date` class, that we'll cover later.
註:日期可以以內建 `Date` 類別的物件來儲存,我們晚點會介紹。
Loading