存储“未读”标志
重要性:5
有一个消息数组
let messages = [
{text: "Hello", from: "John"},
{text: "How goes?", from: "John"},
{text: "See you soon", from: "Alice"}
];
您的代码可以访问它,但消息由其他人的代码管理。新消息被添加,旧消息被定期删除,您不知道它发生的准确时间。
现在,您可以使用哪种数据结构来存储有关消息“是否已读”的信息?该结构必须适合于针对给定消息对象给出“是否已读”的答案。
附注:当消息从 messages
中删除时,它也应该从您的结构中消失。
附注:我们不应该修改消息对象,向它们添加我们的属性。由于它们由其他人的代码管理,这可能会导致不良后果。
让我们将已读消息存储在 WeakSet
中
let messages = [
{text: "Hello", from: "John"},
{text: "How goes?", from: "John"},
{text: "See you soon", from: "Alice"}
];
let readMessages = new WeakSet();
// two messages have been read
readMessages.add(messages[0]);
readMessages.add(messages[1]);
// readMessages has 2 elements
// ...let's read the first message again!
readMessages.add(messages[0]);
// readMessages still has 2 unique elements
// answer: was the message[0] read?
alert("Read message 0: " + readMessages.has(messages[0])); // true
messages.shift();
// now readMessages has 1 element (technically memory may be cleaned later)
WeakSet
允许存储一组消息,并轻松检查消息是否存在。
它会自动清理自身。权衡是,我们无法遍历它,也无法直接获取“所有已读消息”。但我们可以通过遍历所有消息并过滤掉集合中的消息来实现。
另一个不同的解决方案是在消息被读取后添加一个属性,例如 message.isRead=true
。由于消息对象由其他代码管理,因此通常不建议这样做,但我们可以使用符号属性来避免冲突。
像这样
// the symbolic property is only known to our code
let isRead = Symbol("isRead");
messages[0][isRead] = true;
现在第三方代码可能不会看到我们的额外属性。
虽然符号可以降低出现问题的概率,但从架构的角度来看,使用 WeakSet
更好。