"未既読" フラグを格納する
重要性: 5
メッセージの配列があります:
let messages = [
{text: "Hello", from: "John"},
{text: "How goes?", from: "John"},
{text: "See you soon", from: "Alice"}
];
あなたのコードでそれにアクセスできますが、メッセージは他の誰かのコードで管理されています。そのコードによって新しいメッセージが追加され、古いものが定期的に削除されます。そして、あなたはそれが発生する正確なタイミングを知りません。
今、メッセージを “読んだ” かの情報を格納するために使えるのはどのデータ構造でしょうか?その構造は与えられたメッセージオブジェクトに対して、“読んだか?” という解答を与えるのに適したものでなければなりません。
P.S メッセージが messages
から削除されたとき、あなたの構造からも同様に消える必要があります。
P.P.S. 私たちはメッセージオブジェクトを直接変更すべきではありません。ほかの誰かのコードによって管理されている場合、余分なプロパティの追加は悪い結果になる可能性があります。
ここでの良い選択肢は WeakSet
です:
let messages = [
{text: "Hello", from: "John"},
{text: "How goes?", from: "John"},
{text: "See you soon", from: "Alice"}
];
let readMessages = new WeakSet();
// 2つのメッセージは読まれました
readMessages.add(messages[0]);
readMessages.add(messages[1]);
// readMessages は2つの要素を持っています
// ...再び最初のメッセージを読みましょう!
readMessages.add(messages[0]);
// readMessages は依然として2つのユニークな要素をもっています
// 答え: message[0] は読んだ?
alert("Read message 0: " + readMessages.has(messages[0])); // true
messages.shift();
// これで readMessages の要素は1つです(技術的にはメモリは後ほどクリーンされるかもしれません)
WeakSet
でメッセージのセットを格納し、その中でメッセージの存在を簡単に確認することができます。
それは自動的に自身をクリーンアップします。トレードオフはそれをイテレートすることができないことです。私たちは直接 “すべての既読メッセージ” を取得することができません。しかし、すべての messages をイテレートし、set 中のものをフィルタリングすることでそれを実現できます。
P.S メッセージが誰か他の人のコードで管理されている場合、各メッセージに同時のプロパティを追加することは危険です。が、衝突を回避するためにシンボルでそれをすることができます。
このようになります:
// シンボリックプロパティは我々のコードだけが知っています
let isRead = Symbol("isRead");
messages[0][isRead] = true;
これで、たとえ他のコードがメッセージプロパティのために for..in
ループを使っても、隠しフラグは表示されません。