Guida completa al metodo substring() di JavaScript

La substring() di JavaScript sembra innocua. Ma morde con argomenti scambiati e tolleranza per NaN: fa cascare anche i veterani.

substring() di JavaScript: bizzarra, comoda, un casino da capire — theAIcatchup

Key Takeaways

  • substring() scambia da sola gli argomenti e tollera NaN/negativi — comodo, ma nasconde bug.
  • Meglio slice() per negativi e prevedibilità; substring solo per roba legacy tollerante.
  • Valida sempre gli indici: le stringhe JS massacrano emoji UTF-8 senza attenzione.

La substring fa schifo — a volte.

Ti promette un semplice ritaglio di stringa. Prende i caratteri tra due indici. Restituisce una stringa fresca. Niente mutazioni, le stringhe sono immutabili comunque. Ma porca miseria, gli sgambetti. Gli sviluppatori ci cascano ogni giorno, pure dopo dieci anni a maneggiare JS.

Ecco questa chicca dalla documentazione:

Il metodo substring() estrae una porzione di stringa tra un indice di inizio e uno di fine, restituendo la parte estratta come nuova stringa. La stringa originale non viene mai modificata: in JavaScript le stringhe sono immutabili.

Semplice, no? Finché non le dai input schifosi.

Perché substring() ti scambia gli argomenti?

Immagina: “Hello, World!”.substring(5, 0). Ti aspetti robaccia o un errore. Macché. Ti spara “Hello”. Ha scambiato gli argomenti al posto tuo. Che balia gentile, JS. Ma slice()? Ti dà una stringa vuota. substr() (pace all’anima sua) spara errori sui negativi.

È tollerante. Troppo. I novellini la adorano: niente crash. I pro la odiano: la prevedibilità conta. Ecco il casino:

const str = "Hello, World!";
console.log(str.substring(5, 0)); // "Hello" — scambiato!
console.log(str.slice(5, 0));     // ""
console.log(str.substring(-3));   // Stringa intera — i negativi diventano 0

E NaN? Vale 0. Indice oltre la lunghezza? Si ferma a .length. È come se JS ti dicesse: “Dai, dopo mi ringrazierai”. Non lo farai.

Questo scambio automatico? Unico di substring. Nato ai tempi di Netscape, quando i browser crashavano per un niente. Bagaglio storico: ci portiamo dietro la clemenza anni ‘90 nel 2024.

Un paragrafo. Bum.

Indici delle stringhe: a zero, ovvio. “JavaScript”: J=0, a=1, …, t=9. substring(start, end) prende [start, end). Fine esclusa, come array.slice o i for-loop.

Visualizza gli spazi:

|J|a|v|a|S|c|r|i|p|t| 0 1 2 3 4 5 6 7 8 9 10

substring(0,4): ^----^ “Java”. Lunghezza? 4-0=4. Ovvio.

Ma provi coi negativi, e puff — start=0. Niente slicing dalla fine. Lo vuoi? Usa slice(-3). substring finge che intendessi dall’inizio. subdolo.

substring() contro slice() in JavaScript: la faida eterna

Slice è il fratello figo di substring. Gestisce i negativi. Niente scambi. Più rigido, più sano. Dalla fine? slice(-5) centra il bersaglio. substring(-5)? Stringa intera.

const lang = "JavaScript";
console.log(lang.slice(0,4));  // "Java"
console.log(lang.slice(-6));    // "Script" — magia dal fondo
console.log(lang.substring(-6)); // "JavaScript" — fallimento

Perché usare substring? Codice legacy. O quella tolleranza agli scambi nei parser. Ma JS moderno? Slice a go go. substring è come usare innerHTML invece di textContent: funziona, ma perché?

Prestazioni? Irrilevanti. Entrambe O(n). I benchmark dicono che slice vince nei loop, ma chi taglia miliardi? La mia hot take unica: substring sopravvive perché i tutorial copiano-incolla MDN del 2005. Camera d’eco. Scommetto: in ES2030, le string views li ammazzano entrambi. Niente più copie.

Uso reale: trucchi URL. Path.substring(1) butta la slash iniziale. Parsing email:

const email = "[email protected]";
const at = email.indexOf('@');
const user = email.substring(0, at); // "dev"
const domain = email.substring(at+1); // "example.com"

Utilissimo. Ma indexOf fallisce su email storpiate? Crash all’app. Valida prima, campione.

Troncamento: title.substring(0,50) + ‘…’. Ok — finché non arrivi a UTF-8 multibyte. “😂”.length=1? No, 4 byte. substring massacra gli emoji. Usa cluster di graphemi o librerie. Le stringhe JS: code point, non caratteri. 2015 ti chiama: aggiorna.

Trappole comuni. Off-by-one: substring(0, len) prende tutto. len=string.length? Perfetto. Sbagli? Parziale. Gli scambi nascondono bug: substring(10,5) funziona come (5,10). Errore mascherato.

TypeScript? string.substring(start?: number, end?: number): string. Lasco. Aggiungi overload per sicurezza.

```ts function safeSub(str: string, start: number, end?: number): string { const s = Math.max(0, start); const e =

Sarah Chen
Written by

AI research editor covering LLMs, benchmarks, and the race between frontier labs. Previously at MIT CSAIL.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by dev.to