назад до уроку

Зберігати мітки "непрочитане"

важливість: 5

Є масив повідомлень:

let messages = [
  {text: "Привіт", from: "Іван"},
  {text: "Як справи?", from: "Іван"},
  {text: "До зустрічі", from: "Аліса"}
];

Ваш код може отримати доступ до нього, але повідомлення керуються чужим кодом. Нові повідомлення додаються, старі видаляються регулярно цим кодом, і ви не знаєте точних моментів, коли це станеться.

Тепер, яку структуру даних ви могли б використати для зберігання інформації про те, чи було повідомлення прочитаним? Структура повинна добре підходити, щоб дати відповідь на питання “чи він прочитаний?” для об’єкта даного повідомлення.

P.S. Коли повідомлення видаляється з messages, воно також повинне зникнути з вашої структури.

P.P.S. Ми не повинні змінювати об’єкти повідомлення, додаючи до них наші властивості. Оскільки вони керуються іншим кодом, це може призвести до поганих наслідків.

Збережемо прочитані повідомлення у WeakSet:

let messages = [
  {text: "Привіт", from: "Іван"},
  {text: "Як справи?", from: "Іван"},
  {text: "До зустрічі", from: "Аліса"}
];

let readMessages = new WeakSet();

// були прочитані два повідомлення
readMessages.add(messages[0]);
readMessages.add(messages[1]);
// readMessages має 2 елементи

// ...давайте знову прочитаємо перше повідомлення!
readMessages.add(messages[0]);
// readMessages все ще має 2 унікальних елементів

// відповідь: чи було messages[0] прочитано?
alert("Прочитано повідомлення 0: " + readMessages.has(messages[0])); // true

messages.shift();
// зараз readMessages має 1 елемент (з технічної точки зору пам’ять може бути очищена пізніше)

WeakSet дозволяє зберігати набір повідомлень і легко перевірити наявність повідомлення в наборі.

Він автоматично очищає себе. Компроміс полягає в тому, що ми не можемо ітеруватися через нього, не можемо отримати “всі прочитані повідомлення” від нього безпосередньо. Але ми можемо це зробити, ітеруючись через всі повідомлення та відфільтрувавши тих, що знаходяться у наборі.

Інше рішення може полягати у додаванні властивості message.isRead=true до повідомлення після його прочитання. Оскільки об’єкти повідомлень керуються іншим кодом, це, як правило, збентежує, але ми можемо використовувати символьну властивість, щоб уникнути конфліктів.

Ось так:

// символьна властивість відома лише в нашому коді
let isRead = Symbol("isRead");
messages[0][isRead] = true;

Тепер сторонній код, ймовірно, не побачить нашу додаткову властивість.

Незважаючи на те, що символи дозволяють знизити ймовірність проблем, використання WeakSet краще з архітектурної точки зору.