In JavaScript esistono poche funzioni che suscitano reazioni così forti come eval(). Da un lato rappresenta una capacità estrema del linguaggio, quella di eseguire codice a runtime partendo da una stringa. Dall'altro è universalmente considerata una pratica da evitare nella quasi totalità dei casi.
Il motivo non è legato a una moda o a una regola arbitraria. eval() introduce una serie di problemi che riguardano sicurezza, prestazioni, leggibilità e manutenibilità del codice. Comprendere davvero perché evitarla significa fare un passo importante verso uno sviluppo più consapevole.
Una funzione potente ma pericolosa. Che cosa fa davvero eval()?
La funzione eval() prende una stringa e la esegue come codice JavaScript nel contesto corrente. Questo significa che il codice passato a eval() ha accesso alle variabili locali, può modificarle e può influenzare direttamente l'ambiente in cui viene eseguito.Un esempio molto semplice chiarisce il comportamento:
const x = 10;
eval("console.log(x + 5)");
In questo caso la funzione esegue il codice e stampa il risultato. Fin qui può sembrare utile, quasi elegante. Ma è proprio questa flessibilità a rappresentare il problema. Il codice non è più statico e prevedibile. Diventa dinamico, costruito a runtime, spesso a partire da stringhe che possono arrivare da fonti esterne.
Il rischio più grande riguarda la sicurezza
Il motivo principale per cui eval() è sconsigliata riguarda la sicurezza. Eseguire codice generato dinamicamente apre la porta a vulnerabilità molto gravi, in particolare agli attacchi di tipo injection.
Immaginiamo un caso apparentemente innocuo:
function calcola(input) {
return eval(input);
}
calcola("2 + 2");
Se input proviene da una fonte non controllata, come un campo di input utente o una risposta da un'API, il rischio diventa immediato:
calcola("alert('Hackerato!')");
Oppure, in contesti più critici:
calcola("fetch('/dati-sensibili').then(r => r.text()).then(console.log)");
In pratica si sta dando a un utente la possibilità di eseguire codice arbitrario. Questo tipo di vulnerabilità è tra le più pericolose in assoluto.
In ambienti server-side, come Node.js, il rischio è ancora maggiore. Un uso improprio di eval() può portare all'esecuzione di codice malevolo con accesso completo al sistema.
Il costo nascosto di eval()
Oltre alla sicurezza, eval() ha un impatto negativo anche sulle prestazioni. Oggi i motori JavaScript moderni sono estremamente, ma queste ottimizzazioni si basano sulla prevedibilità del codice.
Quando si utilizza eval(), il motore non può sapere in anticipo cosa verrà eseguito. Questo impedisce molte ottimizzazioni, costringendo il runtime a trattare quella parte di codice in modo più conservativo.
In pratica, l'uso di eval() può rallentare l'intera esecuzione, non solo la singola istruzione.
Un esempio può sembrare banale:
const codice = "let a = 1 + 2";
eval(codice);
Ma il problema non è l'operazione in sé. È il fatto che il motore deve analizzare e interpretare quella stringa come codice ogni volta che viene eseguita.
Debugging e manutenzione
Un altro aspetto spesso sottovalutato riguarda la leggibilità del codice. Quando si usa eval() il flusso logico dell'applicazione diventa meno chiaro.
Il codice non è più completamente visibile nel file sorgente. Parte della logica è nascosta dentro stringhe, spesso costruite dinamicamente.
Questo rende molto più difficile fare debugging. Gli errori generati da eval() possono essere poco chiari e difficili da tracciare. Le stack trace diventano meno utili, perché il codice eseguito non ha una posizione stabile nel file.
Immaginiamo una situazione più complessa:
function eseguiOperazione(op, a, b) {
return eval(`${a} ${op} ${b}`);
}
Qui il comportamento dipende da una stringa. Se qualcosa va storto, capire dove e perché richiede molto più tempo rispetto a una funzione esplicita.
Problemi di scope e comportamento imprevedibile
eval() ha accesso allo scope locale, e questo può generare effetti collaterali difficili da prevedere.
function test() {
let valore = 10;
eval("valore = 50");
return valore;
}
console.log(test());
In questo caso eval()
Alternative più sicure
La buona notizia è che nella maggior parte dei casi eval() non è necessario. Esistono alternative molto più sicure e leggibili. Se si tratta di parsare JSON, esiste JSON.parse:
const dati = JSON.parse('{"nome": "Mario"}');
È sicuro e non esegue codice arbitrario.
Se si vuole eseguire operazioni dinamiche, spesso è possibile usare oggetti o funzioni mappate:
const operazioni = {
somma: (a, b) => a + b,
sottrai: (a, b) => a - b
};
function esegui(op, a, b) {
return operazioni[op](a, b);
}
Questo approccio è molto più sicuro e leggibile.
Se invece si ha bisogno di interpretare espressioni complesse, esistono librerie dedicate che implementano parser controllati, senza eseguire codice arbitrario.
Quando viene ancora usato eval()
Ci sono casi molto particolari in cui eval() può avere senso, per esempio in strumenti di debugging, ambienti di scripting controllati o motori di template molto specifici. Anche in questi contesti, però, spesso può essere sostituito da soluzioni più sicure.
Nel codice applicativo quotidiano, soprattutto lato frontend o backend web, l'uso di eval() è quasi sempre un segnale di un design migliorabile.
Una questione di mentalità
Evitare eval() significa preferire strutture esplicite, prevedibili e verificabili. JavaScript è un linguaggio flessibile, ma questa flessibilità deve essere gestita con attenzione. Strumenti come eval() esistono perché il linguaggio lo permette, non perché siano sempre la scelta giusta.
Nel tempo, imparare a riconoscere quando una soluzione è troppo dinamica e potenzialmente pericolosa diventa una competenza fondamentale. Perché evitarla sempre è quasi sempre la scelta giusta
Alla fine, il motivo per cui eval() è sconsigliata è semplice. Introduce più problemi di quanti ne risolva. Complica il codice, riduce la sicurezza, peggiora le prestazioni e rende più difficile la manutenzione.
Nella maggior parte dei casi esiste sempre un'alternativa migliore. Più chiara, più sicura e più performante. E quando una funzione ha così tanti svantaggi rispetto alle alternative, la scelta migliore è non usarla.