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 =