venerdì 3 ottobre 2025

Corso di JavaScript & Programmazione Web: 2 – Fondamenti di programmazione

2 — Fondamenti di programmazione

Argomenti: variabili (let, const, var), tipi di dato (numeri, stringhe, booleani), operatori matematici e logici.
Attività finale: progettare e implementare una calcolatrice base (console + semplice UI).


Obiettivi formativi

Al termine del modulo gli studenti saranno in grado di:

  • Distinguere e usare correttamente let, const e var (scope, riassegnazione, hoisting).

  • Riconoscere i tipi di dato primitivi principali (Number, String, Boolean) e i casi speciali (NaN, Infinity, BigInt).

  • Applicare operatori aritmetici, di confronto e logici in modo corretto e consapevole.

  • Gestire i problemi più comuni legati all’aritmetica in virgola mobile e adottare strategie di compensazione.

  • Sviluppare una semplice calcolatrice che legga input, validi i dati e produca risultati corretti (con gestione errori).

Linguaggio esemplificativo usato: JavaScript (ES6+) — perché let/const/var sono tipici di JS e utili per esercitazioni pratiche sul web.


Materiali richiesti

  • PC con editor (VSCode, Sublime, ecc.)

  • Browser moderno (per eseguire la versione web della calcolatrice)

  • Console del browser (DevTools) per esercizi interattivi


Struttura temporale dettagliata (180 min)

  1. Introduzione & obiettivi — 10 min

  2. Variabili: let, const, var — 35 min

    • definizioni, scope, hoisting, esempi, best practice

  3. Tipi di dato: number, string, boolean (+ speciali) — 30 min

    • esempi, conversioni, typeof, NaN, Infinity, BigInt

  4. Operatori matematici e problema della virgola mobile — 30 min

          • / % **, ++/--, precedence, problemi e soluzioni

  5. Operatori logici & confronto — 20 min

    • &&, ||, !, truthy/falsy, == vs ===

  6. Pausa breve — 10 min

  7. Laboratorio guidato: calcolatrice base (console → UI) — 30 min

    • sviluppo passo-passo, gestione input, validazione, casi limite

  8. Test, debug, Q&A e compiti — 15 min


1) Variabili — let, const, var (approfondimento)

Concetti chiave

  • const: riferimento immutabile di binding. Non si può riassegnare il nome a un altro valore. Se il valore è un oggetto/array, le sue proprietà/elementi possono comunque cambiare.

  • let: variabile riassegnabile con scope di blocco ( { ... } ). Usare per valori che cambiano.

  • var: scope di funzione (o globale se dichiarato fuori funzione), soggetto a hoisting (dichiarazione "spostata" in cima), comportamento problematico — evitare salvo comprensione storica.

Esempi pratici

// const
const PI = 3.14159;
PI = 3; // TypeError: Assignment to constant variable.
// let
let counter = 0;
if (true) {
let counter = 10; // scope diverso: non sovrascrive l'esterno
console.log(counter); // 10
}
console.log(counter); // 0
// var (evitare)
function f() {
if (true) {
var x = 1; // scope di funzione
}
console.log(x); // 1
}

Hoisting e Temporal Dead Zone (TDZ)

  • var x; è "hoisted" (dichiarazione spostata all'inizio), quindi console.log(x) prima della dichiarazione stampa undefined.

  • let/const sono anch’essi "visibili" ma non utilizzabili prima della dichiarazione — questo causa ReferenceError se provi ad accedervi nella TDZ.

Best practice: preferire const per valori che non cambiano, let quando serve riassegnare. Evitare var.


2) Tipi di dato: Number, String, Boolean (con casi speciali)

Number (IEEE 754 double precision)

  • Rappresentazione in virgola mobile → attenzioni a precisione.

  • Esempi: 42, 3.14, -0 (significato particolare), NaN, Infinity.

typeof 123; // "number"
typeof 3.14; // "number"
Number.isNaN(NaN); // true
1 / 0; // Infinity

Nota su NaN: NaN !== NaN. Usare Number.isNaN() per verificare.

BigInt

  • Per interi molto grandi: 123n è un BigInt (JS moderno).

const big = 9007199254740993n; // oltre MAX_SAFE_INTEGER

String

  • Testo: concatenazione con +, template literal con backticks `... ${expr} ...`.

"ciao" + " mondo"; // "ciao mondo"
`2 + 3 = ${2 + 3}`; // "2 + 3 = 5"

Boolean

  • true / false. Molte operazioni e valori sono truthy o falsy (es. 0, "", null, undefined, NaN sono falsy).

Type coercion (attenzione!)

  • "2" + 3"23" (concatenazione).

  • +"3" o Number("3") converte a numero.

  • Preferire conversioni esplicite.


3) Operatori matematici e aritmetica (con attenzione alla precisione)

Operatori principali

  • Aritmetici: +, -, *, /, % (modulo), ** (potenza)

  • Incremento/decremento: ++, --

  • Assegnazione composta: +=, -=, *=, /=

Precedenza (breve)

  1. ()

  2. **

  3. *, /, %

  4. +, -

  5. assegnazioni

Virgola mobile: problema classico

Esempio noto: 0.1 + 0.2 in JavaScript restituisce 0.30000000000000004 (perché i numeri sono rappresentati in base 2 e non tutte le frazioni decimali sono esatte).

Dimostrazione semplice (metodo stabile): se vuoi sommare 0.1 e 0.2 con esattezza decimale di 1 cifra:

  • moltiplica per 10: 0.1 * 10 = 1, 0.2 * 10 = 2

  • somma intera: 1 + 2 = 3

  • riporta a scala decimale: 3 / 10 = 0.3

Esempio pratico in codice (soluzione semplice):

function preciseAdd(a, b) {
const sA = a.toString();
const sB = b.toString();
const dA = (sA.split('.')[1] || '').length;
const dB = (sB.split('.')[1] || '').length;
const factor = 10 ** Math.max(dA, dB);
return (Math.round(a * factor) + Math.round(b * factor)) / factor;
}
preciseAdd(0.1, 0.2); // 0.3

Nota: per applicazioni finanziarie reali usare librerie per aritmetica decimale (es. decimal.js) o tipi specifici.

Divisione per zero

  • 1 / 0Infinity

  • 0 / 0NaN

Modulo con numeri negativi

  • % restituisce il resto, ma il segno segue il dividendo in JS: -5 % 3 === -2.


4) Operatorii di confronto e logici

Confronti

  • == (uguaglianza non rigorosa): effettua coercizioni.

  • === (uguaglianza stretta): no coercione — preferire ===.

  • != vs !== analoghi.

Esempi insidiosi

0 == false; // true
0 === false; // false
"" == 0; // true
null == undefined; // true
null === undefined; // false

Regola: usare === a meno di esplicita necessità di coercizione.

Logici (&&, ||, !)

  • Valutano operandi e short-circuit:

    • a && b: restituisce a se falsy, altrimenti b.

    • a || b: restituisce a se truthy, altrimenti b.

  • Utile per default: const name = input || "Anonimo" (ma attenzione se input === "").

Esempio:

function getDefault(input) {
return input || "default";
}
getDefault(""); // "default"
getDefault("ciao"); // "ciao"

Se vuoi distinguere "" da null/undefined, usa ?? (nullish coalescing) in JS moderno:

input ?? "default"; // ritorna input se non null/undefined; altrimenti default

5) Esercizi pratici (progressivi)

Esercizio A — rapido (console)

Scrivi espressioni che valutino a true:

  1. 0 == false? (spiegare il perché)

  2. 0 === false? (spiegare perché no)

Soluzione (spiegata):

  1. 0 == false è true perché == converte false in 0 prima del confronto.

  2. 0 === false è false perché il tipo number non è uguale al tipo boolean.


Esercizio B — gestione stringhe e numeri

Dato l'input utente a = "3.5", b = "2", calcola la somma numerica corretta.

Soluzione:

const a = "3.5";
const b = "2";
const sum = parseFloat(a) + parseFloat(b); // 5.5

Esercizio C — problema di virgola mobile

Dimostrare il comportamento di 0.1 + 0.2 e risolverlo con scaling:

console.log(0.1 + 0.2); // 0.30000000000000004
console.log( (0.1*10 + 0.2*10) / 10 ); // 0.3

Discussione: spiegare perché accade e come risolvere per casi didattici.


6) Laboratorio guidato: Calcolatrice base

Requisiti minimi

  • Accetta due numeri (decimali possibili).

  • Opera le quattro funzioni di base: +, -, *, /.

  • Controlla input non numerico e divisione per zero.

  • Mostra risultato in modo leggibile (es. 2 decimali opzionali).

Versione 1 — Console (base)

function calc(a, b, op) {
const x = parseFloat(a);
const y = parseFloat(b);
if (Number.isNaN(x) || Number.isNaN(y)) {
return 'Errore: input non numerico';
}
switch(op) {
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/':
if (y === 0) return 'Errore: divisione per zero';
return x / y;
default:
return 'Operatore non supportato';
}
}
console.log(calc("2.5", "1.2", "+")); // 3.7

Versione 2 — semplice UI HTML + JS (pulita e funzionante)

Copiare questo file .html e aprirlo con un browser:

<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8" />
<title>Calcolatrice Base</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
.box { max-width: 420px; margin: auto; background:#f7f7f7; padding:16px; border-radius:8px; }
input, select, button { font-size:1rem; padding:8px; margin:6px 0; width:100%; box-sizing:border-box; }
.result { margin-top:12px; padding:10px; background:#222; color:#fff; border-radius:6px; text-align:center; }
</style>
</head>
<body>
<div class="box">
<h2>Calcolatrice Base</h2>
<label>Primo numero
<input id="a" type="text" placeholder="es. 3.5" />
</label>
<label>Secondo numero
<input id="b" type="text" placeholder="es. 2" />
</label>
<label>Operazione
<select id="op">
<option value="+">Addizione (+)</option>
<option value="-">Sottrazione (-)</option>
<option value="*">Moltiplicazione (*)</option>
<option value="/">Divisione (/)</option>
</select>
</label>
<button id="calcBtn">Calcola</button>
<div id="result" class="result" aria-live="polite">Risultato: —</div>
</div>
<script>
function safeParseNumber(s) {
if (s === null || s === undefined) return NaN;
// rimuove spazi e usa la virgola come possibile separatore
s = s.trim().replace(',', '.');
return Number(s);
}
function calc(aRaw, bRaw, op) {
const a = safeParseNumber(aRaw);
const b = safeParseNumber(bRaw);
if (Number.isNaN(a) || Number.isNaN(b)) {
return { ok: false, msg: 'Errore: uno dei due input non è un numero valido' };
}
if (op === '/' && b === 0) {
return { ok: false, msg: 'Errore: divisione per zero' };
}
// operazione: usiamo parseFloat-style, ma per risultati precisi usare preciseAdd ecc.
let res;
switch (op) {
case '+': res = a + b; break;
case '-': res = a - b; break;
case '*': res = a * b; break;
case '/': res = a / b; break;
default: return { ok: false, msg: 'Operatore non supportato' };
}
// formattazione: mostra fino a 10 cifre significative evitando notazione esponenziale per numeri piccoli
const display = Number.isFinite(res) ? Number(res.toPrecision(12)).toString() : String(res);
return { ok: true, value: display };
}
document.getElementById('calcBtn').addEventListener('click', () => {
const a = document.getElementById('a').value;
const b = document.getElementById('b').value;
const op = document.getElementById('op').value;
const out = calc(a, b, op);
const el = document.getElementById('result');
if (!out.ok) {
el.textContent = out.msg;
el.style.background = '#c0392b';
} else {
el.textContent = 'Risultato: ' + out.value;
el.style.background = '#2ecc71';
}
});
</script>
</body>
</html>

Spiegazioni implementative:

  • safeParseNumber supporta la virgola come separatore decimale (utile per utenti italiani).

  • calc verifica input, protegge dalla divisione per zero e restituisce sempre oggetti {ok, value/msg} per gestire errori con chiarezza.

  • toPrecision(12) evita stampare la lunga 0.30000000000000004 in caso di somme come 0.1 + 0.2; si potrebbe usare la versione preciseAdd per risultati esatti quando necessario.


7) Esercizi di consolidamento (da svolgere a casa o in coppia)

  1. Estendere la calcolatrice per supportare la percentuale: es. a % → restituisce a / 100.

  2. Memoria: aggiungere tasti M+, MC, MR (memoria).

  3. Chain calc (intermedio): permettere insert di più operazioni in un array e ridurle (es. 3 + 4 * 2). Nota: valutare precedenza operazioni.

  4. Precisione avanzata: implementare funzioni preciseAdd, preciseSub, preciseMul, preciseDiv che usano scaling intero per ottenere risultati corretti per numeri con molti decimali.

  5. Unit tests: scrivere test (con Jest o simple assertions) per le funzioni della calcolatrice.


8) Rubrica di valutazione (sintetica)

  • Completezza funzionale (40%): tutte le operazioni richieste implementate; gestione errori.

  • Robustezza e validazione (25%): input non numerici, divisione per zero, formattazione.

  • Pulizia codice e documentazione (15%): funzioni modulari, commenti, nomi chiari.

  • UI/usabilità (10%): chiarezza dei messaggi e ergonomia.

  • Extra/estensioni (10%): gestione percentuali, memoria, test automatici.


9) Cheat-sheet rapido (da tenere sul banco)

  • Dichiarazioni: const a = 1; let b = 2; var c = 3;

  • Convertire a numero: Number("3.14"), parseFloat("3,14".replace(',', '.'))

  • Verifica NaN: Number.isNaN(x)

  • Confronto corretto: usare === e !==

  • String template: `Risultato: ${x}`

  • Profilo virgola mobile: 0.1 + 0.2 === 0.3false in JS; usare scaling per precisione.


10) Risorse consigliate (per approfondire)

  • MDN Web Docs — guide su let/const/var, tipi, operatori (ottima risorsa per esempi e compatibilità).

  • Eloquent JavaScript (Marijn Haverbeke) — capitoli introduttivi su tipi e strutture.

  • Guide su aritmetica decimale / librerie (es. decimal.js) per applicazioni finanziarie.


Conclusione rapida

Questo modulo da 3 ore è pensato per dare solide basi pratiche: non si tratta solo di imparare sintassi, ma di pensare ai tipi, ai limiti della macchina (virgola mobile), e di progettare codice che gestisca correttamente gli errori. La calcolatrice è l’esercizio ideale perché obbliga a toccare tutte le tematiche: parsing, error handling, operatori e interfaccia utente.

Nessun commento:

Posta un commento

Corso Fondamenti di Informatica e Reti: 6 Reti di computer e Internet

Reti di computer e Internet Introduzione Prova a pensare alla vita quotidiana senza reti informatiche: niente messaggi WhatsApp, niente m...