Memorizzare le bandiere non visualizzate
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.