17 marzo 2025

Variabili e Tipi di Dati

var, let, const

Una delle caratteristiche principali introdotte con ES6 è l’aggiunta di let e const per la dichiarazione delle variabili. Prima di ES6, var era il metodo principale per dichiarare variabili, ma presentava diversi problemi.

Var

L’ambito di una variabile definisce dove può essere accessibile. Le variabili dichiarate con var hanno un ambito globale o di funzione. Se dichiarate a livello globale, possono essere accessibili ovunque nella finestra.

Esempio:

var greeter = "hey hi";
var greeter = "say Hello instead"; // Re-declaration is allowed

Il problema con var è che la ri-dichiarazione di una variabile può portare a risultati inaspettati nel codice.

Let

let è stato introdotto per migliorare var. Ha un ambito di blocco, il che significa che può essere accessibile solo all’interno del blocco {} in cui è stato dichiarato. Sebbene le variabili dichiarate con let possano essere aggiornate, non possono essere ri-dichiarate.

Esempio:

let message = "Hello";
message = "Hi"; // Allowed
let message = "Hey"; // Syntax Error

Un’altra differenza fondamentale è il hoisting. Quando si tenta di accedere a una variabile sollevata prima della sua dichiarazione:

Const

Le variabili dichiarate con const sono costanti, il che significa che i loro valori non possono essere aggiornati né ri-dichiarati. Come let, const ha un ambito di blocco.

Esempio:

const PI = 3.1416;
PI = 3.14; // TypeError: Assignment to constant variable

Tuttavia, gli oggetti e gli array dichiarati con const possono essere modificati:

const person = { name: "John" };
person.name = "Jane"; // Allowed

Tipi Primitivi

I tipi primitivi definiscono valori immutabili e sono rappresentati al livello più basso di JavaScript. Questi tipi includono:

Tipotypeof return valueObject Wrapper
Null”object”N/A
Undefined”undefined”N/A
Boolean”boolean”Boolean
Number”number”Number
BigInt”bigint”BigInt
String”string”String
Symbol”symbol”Symbol

Null

Rappresenta un’assenza intenzionale di un valore.

let x = null;

Undefined

Rappresenta una variabile non inizializzata.

let y;
console.log(y); // undefined

Boolean

Rappresenta i valori true o false, comunemente utilizzati nelle condizioni.

let isActive = true;

Number

JavaScript utilizza numeri in virgola mobile a doppia precisione a 64 bit.

let num = 42;
let big = Number.MAX_SAFE_INTEGER;

Valori speciali:

console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(0 / 0); // NaN

BigInt

Per gestire interi oltre Number.MAX_SAFE_INTEGER.

let bigInt = 123456789012345678901234567890n;

String

Dati testuali, immutabili.

let greeting = "Hello, world!";

Symbol

Un identificatore unico, spesso utilizzato per le chiavi delle proprietà degli oggetti.

let sym = Symbol("unique");

Tipi di Riferimento

A differenza dei tipi primitivi, i tipi di riferimento memorizzano indirizzi di memoria invece dei valori.

Oggetti

Gli oggetti memorizzano coppie chiave-valore.

let person = {
  name: "Alice",
  age: 25,
};

Array

Collezioni ordinate di valori.

let numbers = [1, 2, 3, 4, 5];

Funzioni

Un oggetto chiamabile.

function greet() {
  console.log("Hello");
}

Map & Set

Map: Memorizza coppie chiave-valore.

Set: Memorizza valori unici.

Esempio:

let myMap = new Map();
myMap.set("key", "value");

let mySet = new Set([1, 2, 3]);

Questi tipi di riferimento permettono a JavaScript di gestire i dati complessi in modo efficiente.

Template Literals

I template literals, introdotti in ES6, consentono una più semplice interpolazione di stringhe e stringhe su più righe. Questi sono racchiusi tra backtick (`) e supportano espressioni incorporate.

Interpolazione di Stringhe di Base

Puoi incorporare espressioni direttamente all’interno dei template literals utilizzando la sintassi ${}:

let name = "Alice";
let greeting = `Hello, ${name}!`; // String interpolation
console.log(greeting); // "Hello, Alice!"

Stringhe su Più Righe

I template literals rendono anche più facile lavorare con stringhe su più righe:

let multilineString = `This is a
multi-line
string!`;
console.log(multilineString);
// Output:
// This is a
// multi-line
// string!

Espressioni e Calcoli

I template literals permettono espressioni più complesse all’interno di ${}:

let a = 10;
let b = 20;
let result = `The sum of ${a} and ${b} is ${a + b}.`;
console.log(result); // "The sum of 10 and 20 is 30."

Questa funzionalità migliora la leggibilità del codice e riduce la necessità di concatenazione di stringhe.

Nomenclatura

Scegliere nomi di variabili significativi è una pratica fondamentale per scrivere codice leggibile e manutenibile. Ecco alcune migliori pratiche e linee guida per la denominazione delle variabili in JavaScript:

Nomi Descrittivi

Le variabili dovrebbero essere denominate in modo da indicare chiaramente cosa rappresentano. Ad esempio:

let firstName = "Alice"; // Clear and descriptive
let age = 30; // Describes the person's age

Convenzione CamelCase

In JavaScript, si usa comunemente il camelCase per i nomi delle variabili e delle funzioni. La prima parola inizia con una lettera minuscola, e ogni parola successiva inizia con una lettera maiuscola.

let userAge = 25;
let userFullName = "John Doe";

Costanti in Maiuscolo

Per le costanti, è pratica comune usare tutte le lettere maiuscole con gli underscore che separano le parole.

const MAX_USERS = 100;
const API_URL = "https://api.example.com";

Evitare Parole Riservate

Evita di utilizzare parole chiave riservate di JavaScript come let, var, if, else, class, function e altre come nomi di variabili.

Significativo, ma Conciso

Scegli nomi di variabili che siano sia significativi che concisi per garantire chiarezza senza verbosità inutile. Ad esempio, count è migliore di counterVariable, e isActive è più informativo di statusFlag.

Riferimento alla Memoria (Memory Reference)

Primitivi vs Tipi di Riferimento

In JavaScript, le variabili possono contenere valori primitivi o valori di riferimento. Questa distinzione gioca un ruolo fondamentale nel modo in cui i valori vengono memorizzati e manipolati in memoria.

Tipi Primitivi

I tipi primitivi sono memorizzati direttamente in memoria. Quando una variabile viene assegnata a un valore primitivo, il valore stesso viene memorizzato nella variabile:

let x = 10; // x stores the value 10 directly in memory
let y = x; // y now stores a copy of x's value
x = 20; // Changing x does not affect y
console.log(x); // 20
console.log(y); // 10

In questo esempio, x e y memorizzano valori indipendenti. Le modifiche a x non influenzano y.

Tipi di Riferimento

I tipi di riferimento (come oggetti, array e funzioni) sono memorizzati come riferimenti (indirizzi di memoria). Quando una variabile viene assegnata a un valore di tipo riferimento, memorizza l’indirizzo dell’oggetto in memoria, non l’oggetto stesso.

let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 now references the same object as obj1
obj1.name = "Bob"; // Changing obj1 will also affect obj2
console.log(obj1.name); // "Bob"
console.log(obj2.name); // "Bob"

Qui, sia obj1 che obj2 fanno riferimento allo stesso oggetto in memoria. Modificare l’oggetto tramite uno dei due riferimenti influenzerà entrambe le variabili perché puntano alla stessa posizione in memoria.

Passaggio per Valore vs Passaggio per Riferimento

Quando si passano variabili alle funzioni:

Esempio per i tipi primitivi:

function changeValue(num) {
  num = 100;
}

let myNumber = 50;
changeValue(myNumber);
console.log(myNumber); // 50, original value is unchanged

Esempio per i tipi di riferimento:

function changeObject(obj) {
  obj.name = "Charlie";
}

let myObject = { name: "Alice" };
changeObject(myObject);
console.log(myObject.name); // "Charlie", the object is modified

In sintesi, comprendere come JavaScript gestisce i riferimenti in memoria è fondamentale per gestire le variabili, specialmente quando si lavora con tipi di dati complessi come oggetti e array.