torna alle lezioni

Memorizzare le bandiere non visualizzate

importanza: 5

Abbiamo un array di messaggi:

let messages = [
  {text: "Hello", from: "John"},
  {text: "How goes?", from: "John"},
  {text: "See you soon", from: "Alice"}
];

Il vostro codice vi può accedere, ma i messaggi sono gestiti dal codice di qualcun altro. Vengono aggiunti nuovi messaggi, quelli vecchi vengono rimossi, e voi non avete modo di sapere quando ciò accade.

Ora, quale struttura dati potresti utilizzare per memorizzare quali messaggi “sono stati letti”? La struttura deve calzare bene al problema, e rispondere alla domanda “è stato letto?”.

P.S. Quando un messaggio viene rimosso da messages, dovrebbe essere rimosso anche dalla vostra struttura.

P.P.S. Non dovremmo modificare l’oggetto messagge. Poichè se viene gestito dal codice di qualcun altro, aggiungere nuove proprietà potrebbe avere conseguenze disastrose.

Memorizziamo i messaggi letti in WeakSet:

let messages = [
  {text: "Hello", from: "John"},
  {text: "How goes?", from: "John"},
  {text: "See you soon", from: "Alice"}
];

let readMessages = new WeakSet();

//due messaggi sono stati letti
readMessages.add(messages[0]);
readMessages.add(messages[1]);
// readMessages ha due elementi

//...leggiamo nuovamente il primo messaggio!
readMessages.add(messages[0]);
// readMessages ha 2 elementi unici

//risposta: message[0] è stato letto?
alert("Read message 0: " + readMessages.has(messages[0])); // true

messages.shift();
// ora readMessages ha un elemento (tecnicamente la memoria potrebbe essere ripulita dopo)

La struttura WeakSet consente di memorizzare un insieme di messaggi e di verificare facilmente la presenza di un dato messaggio.

Viene ripulita automaticamente. Il lato negativo è che non possiamo eseguire iterazioni. Non possiamo ottenere direttamente “tutti i messaggi letti”. Ma possiamo farlo iterando su tutti i messaggi e filtrando tutti quelli che sono presenti nel 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.

Un’altra soluzione potrebbe essere aggiungere una proprietà come message.isRead=true, ma farlo potrebbe essere pericoloso, se questo oggetto viene gestito dal codice di un’altra persona; per evitare conflitti possiamo utilizzare un symbol.

Come qui:

//la proprietà simbolica è visibile solo al nostro codice
let isRead = Symbol("isRead");
messages[0][isRead] = true;

Ora anche se qualcun altro utilizza for..in per avere accesso a tutte le proprietà di messages, la nostra proprietà sarà segreta.

Although symbols allow to lower the probability of problems, using WeakSet is better from the architectural point of view. Sebbene i simboli permettano una minore probabilità di problemi, utilizzare weakSet è meglio da un punto di vista architetturale.