A parità di risultati, un codice elegante, riusabile e dalle performance migliori è indice di competenza. Vediamo come è possibile migliorare l'uso dei costrutti condizionali in JavaScript, senza impantanarci in una moltitudine di blocchi if/else
, attraverso 4 modalità precise che si avvalgono anche delle nuove funzionalità delle specifiche ECMA.
array.includes, non check multipli
function checkZone(town) {
if (town == 'Milano' || town == 'Torino') {
console.log('Zona: Nord');
}
}
Sebbene questo codice funzioni, cosa succederebbe se le condizioni aumentassero? Un approccio migliore è sicuramente il seguente:
function checkZone(town) {
let nothernTowns = ['Milano', 'Torino', 'Venezia', 'Aosta'];
if (hotColors.includes(colorName)) {
console.log('Zona: Nord');
}
}
Nesting intelligente e return immediato
Aggiungiamo qualche tocco in più all'esempio precedente. Restituiamo un errore se non viene fornito nessun valore e controlliamo tipo di valore e quantità stabilità di valori, loggando l'andamento del codice:
function checkZone(town, inhabitants) {
let nothernTowns = ['Milano', 'Torino', 'Venezia', 'Aosta'];
// check 1
if (town) {
// check 2
if (nothernTowns.includes(town)) {
console.log('Zona: Nord');
// check 3
if (inhabitants > 30000) {
console.log('Densità: Elevata');
}
}
} else {
throw new Error('Nessuna città fornita!');
}
}
Possiamo migliorare le performance del codice andando a migliorare l'annidamento dei controlli chiudendo la funzione al primo errore riscontrato:
function checkZone(town, inhabitants) {
let nothernTowns = ['Milano', 'Torino', 'Venezia', 'Aosta'];
if (!town) throw new Error('Nessuna città fornita!'); // check 1
if (!nothernTowns.includes(town)) return; // check 2
console.log('Zona: Nord');
// check 3
if (inhabitants > 30000) {
console.log('Densità: Elevata');
}
}
Parametri di default
Invece di usare controlli sui valori forniti attraverso una nuova variabile, nel caso in cui vengano forniti valori non previsti come NULL
o undefined
o non vengano forniti valori:
function checkZone(town, inhabitants) {
if (!town) return;
let num = inhabitants || 10000; // check
console.log'`Numero abitanti: ${q} nella città di: ${town}!');
}
possiamo invece usare i valori di default sui parametri delle funzioni, che rendono inutile l'utilizzo di una nuova variabile:
function checkZone(town, inhabitants = 1) { // check
if (!town) return;
console.log('Numero abitanti: ${q} nella città di: ${town}!');
}
I parametri di default sono un argomento molto ampio. In questo esempio ho volutamente preso in considerazione una situazione semplice.
Letterali oggetto o Map al posto di switch
Un controllo condizionale migliore prende in considerazione, al posto dell'operatore switch:
function checkZone(town) {
switch (town) {
case 'nord':
return ['Milano', 'Torino', 'Venezia', 'Aosta'];
case 'centro':
return ['Firenze', 'Roma', 'Pescara', 'Perugia'];
case 'sud':
return ['Palermo', 'Bari', 'Napoli', 'Catanzaro'];
default:
return [];
}
}
l'utilizzo di un letterale oggetto:
let italianTowns = {
nord: ['Milano', 'Torino', 'Venezia', 'Aosta'],
centro: ['Firenze', 'Roma', 'Pescara', 'Perugia'],
sud: ['Palermo', 'Bari', 'Napoli', 'Catanzaro']
};
function checkZone(town) {
return italianTowns[town] || [];
}
o l'oggetto Map (che registra coppie di chiave/valore iterabili)
let italianTowns = new Map()
.set('nord', ['Milano', 'Torino', 'Venezia', 'Aosta'])
.set('centro', ['Firenze', 'Roma', 'Pescara', 'Perugia'])
.set('sud', ['Palermo', 'Bari', 'Napoli', 'Catanzaro']);
function checkZone(town) {
return italianTowns.get(town) || [];
}