Oggetto `String`
Questo articolo spiega l'oggetto String.
La spiegazione copre tutto, dalle basi alle tecniche avanzate, inclusi i problemi legati a Unicode ed espressioni regolari, passo dopo passo e in modo facile da comprendere.
YouTube Video
Oggetto String
Le stringhe in JavaScript sono uno dei tipi più utilizzati nello sviluppo quotidiano.
Differenza tra stringhe primitive e oggetti String
Le stringhe primitive (come "hello") si comportano diversamente dagli oggetti wrapper come new String("hello"). Normalmente, dovresti usare le primitive e c'è poco bisogno di utilizzare la forma oggetto.
1// Primitive string
2const a = "hello";
3
4// String wrapper object
5const b = new String("hello");
6
7console.log(typeof a); // "string"
8console.log(typeof b); // "object"
9console.log(a === b); // false — wrapper objects are not strictly equal
- Questo codice mostra la differenza di tipo tra una primitiva e un wrapper, e come si comportano con il confronto stretto. Nella maggior parte dei casi, evita di usare
new String()e resta sulle primitive.
Modi per creare stringhe (letterali e template literal)
I template literal sono utili per incorporare variabili e scrivere stringhe su più linee. Puoi inserire variabili e valutare espressioni in modo intuitivo.
1const name = "Alice";
2const age = 30;
3
4// Template literal
5const greeting = `Name: ${name}, Age: ${age + 1}`;
6
7console.log(greeting); // "Name: Alice, Age: 31"
- I template literal sono molto leggibili e ideali per costruire stringhe complesse, comprese quelle su più linee.
Metodi comuni (ricerca ed estrazione di sottostringhe)
L'oggetto String ha molti metodi di base.
1const text = "Hello, world! Hello again.";
2
3// search
4console.log(text.indexOf("Hello")); // 0
5console.log(text.indexOf("Hello", 1)); // 13
6console.log(text.includes("world")); // true
7console.log(text.startsWith("Hello")); // true
8console.log(text.endsWith("again.")); // true
9
10// slice / substring
11console.log(text.slice(7, 12)); // "world"
12console.log(text.substring(7, 12)); // "world"
sliceesubstringsono simili, ma gestiscono gli indici negativi in modo diverso.sliceinterpreta i valori negativi come posizioni dalla fine. Sii chiaro su quale usare.
Divisione e unione (split / join)
È comune dividere una stringa in un array per l'elaborazione e poi riunirla.
1const csv = "red,green,blue";
2const arr = csv.split(","); // ["red","green","blue"]
3
4console.log(arr);
5console.log(arr.join(" | ")); // "red | green | blue"
- Un pattern comune è usare
splitper dividere una stringa, processare l'array risultante conmapofiltere poi usarejoinper ricomporlo.
Sostituzione ed espressioni regolari
Il metodo replace sostituisce solo la prima corrispondenza. Se vuoi sostituire tutte le corrispondenze, usa il flag g con un'espressione regolare. Passando una funzione come sostituto, puoi eseguire anche sostituzioni dinamiche.
1const s = "foo 1 foo 2";
2
3// replace first only
4console.log(s.replace("foo", "bar")); // "bar 1 foo 2"
5
6// replace all using regex
7console.log(s.replace(/foo/g, "bar")); // "bar 1 bar 2"
8
9// replace with function
10const r = s.replace(/\d+/g, (match) => String(Number(match) * 10));
11console.log(r); // "foo 10 foo 20"
- Con la sostituzione dinamica tramite una funzione, puoi scrivere in modo conciso codice che analizza e trasforma le corrispondenze.
Conversione di maiuscole/minuscole e normalizzazione
Per il supporto multilingue e il confronto, oltre a toLowerCase e toUpperCase, anche la normalizzazione Unicode (normalize) è importante. Questo è particolarmente necessario quando si confrontano caratteri accentati.
1// Case conversion example:
2// "\u00DF" represents the German letter "ß".
3// In some locales, converting "ß" to uppercase becomes "SS".
4// JavaScript follows this behavior.
5console.log("\u00DF");
6console.log("\u00DF".toUpperCase()); // "SS"
7
8// Unicode normalization example:
9// "e\u0301" is "e" + a combining acute accent.
10// "\u00e9" is the precomposed character "é".
11// These two look the same but are different code point sequences.
12const a = "e\u0301";
13const b = "\u00e9";
14
15console.log(a === b); // false: different underlying code points
16console.log(a.normalize() === b.normalize()); // true: normalized to the same form
- Rappresentazioni Unicode diverse, come legature e caratteri combinati, non saranno uguali così come sono, quindi usa
normalize()prima di confrontare.
Unicode e code point (gestione delle coppie surrogate)
Le stringhe JavaScript sono sequenze di unità di codice UTF-16, quindi alcuni caratteri come le emoji possono occupare due unità di codice per un solo carattere. Per gestire le vere unità di caratteri, usa Array.from, l'operatore spread, o for...of.
1// Emoji composed with multiple code points:
2// "\u{1F469}" = woman, "\u{200D}" = Zero Width Joiner (ZWJ),
3// "\u{1F4BB}" = laptop. Combined, they form a single emoji: 👩💻
4const s = "\u{1F469}\u{200D}\u{1F4BB}";
5console.log(s);
6
7// Length in UTF-16 code units (not actual Unicode characters):
8// Because this emoji uses surrogate pairs + ZWJ, the length may be > 1.
9console.log("Length:", s.length);
10
11// Iterate by Unicode code points (ES6 for...of iterates code points):
12// Each iteration gives a full Unicode character, not UTF-16 units.
13for (const ch of s) {
14 console.log(ch);
15}
16
17// Convert to an array of Unicode characters:
18console.log(Array.from(s));lengthrestituisce il numero di unità di codice, quindi potresti non ottenere il conteggio previsto con emoji o legature.for...ofeArray.fromgestiscono qualcosa di simile ai caratteri visualizzati (cluster di grafemi), ma se hai bisogno di un supporto completo ai grafemi, considera l'uso di una libreria specializzata.
Sostituzione sicura con espressioni regolari (quando si gestisce l'input utente)
Se dimentichi di eseguire l'escape dell'input dell'utente quando lo inserisci in un'espressione regolare, può portare a comportamenti imprevisti e vulnerabilità. Fai sempre l'escape dell'input utente prima di usarlo in un pattern.
1function escapeRegex(s) {
2 return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3}
4
5const userInput = "a+b";
6const pattern = new RegExp(escapeRegex(userInput), "g");
7console.log("a+b a+b".replace(pattern, "X")); // "X X"
- Non usare direttamente le stringhe degli utenti nelle espressioni regolari; effettua sempre l'escape prima di costruire la regex.
Consigli sulle performance: concatenazione e template
Quando concateni molte piccole stringhe in sequenza, metterle in un array e usare join può essere più efficiente. D'altra parte, le template string sono molto leggibili e abbastanza veloci nella maggior parte dei casi.
1// concatenation in loop (less ideal)
2let s = "";
3for (let i = 0; i < 1000; i++) {
4 s += i + ",";
5}
6
7// using array + join (often faster for many pieces)
8const parts = [];
9for (let i = 0; i < 1000; i++) {
10 parts.push(i + ",");
11}
12const s2 = parts.join("");- I motori JavaScript moderni sono molto ottimizzati, quindi non devi preoccuparti delle prestazioni per un piccolo numero di concatenazioni. Tuttavia, se devi concatenare decine di migliaia di volte, usare
joinpuò essere più efficiente.
Tecniche pratiche utili: padding, trim e repeat
trim, padStart, padEnd e repeat sono metodi pratici che risultano particolarmente utili nell’elaborazione quotidiana delle stringhe. Sono spesso utilizzati in situazioni pratiche come la formattazione dei valori di input o la standardizzazione dei formati di output.
1console.log(" hello ".trim()); // "hello"
2console.log("5".padStart(3, "0")); // "005"
3console.log("x".repeat(5)); // "xxxxx"
- Questi metodi possono essere usati per normalizzare l'input di moduli o generare output a larghezza fissa.
Confronto tra stringhe (confronto locale)
localeCompare è efficace per confrontare le stringhe secondo l'ordine del dizionario di lingue diverse. Puoi specificare la lingua e le opzioni di sensibilità (come la distinzione tra maiuscole e minuscole).
1console.log(
2 "\u00E4".localeCompare("z", "de")
3); // may be -1 or other depending on locale
4
5console.log(
6 "a".localeCompare("A", undefined, { sensitivity: "base" })
7); // 0
- Per confronti internazionalizzati, usa
localeComparee specifica la localizzazione e le opzioni appropriate.
Esempio pratico: convertire una riga CSV in un oggetto (workflow pratico)
Un esempio comune consiste nell'analizzare una singola riga CSV in un oggetto usando una combinazione di split, trim e map. Per campi tra virgolette o file CSV complessi, usa un parser CSV dedicato.
1// simple CSV parse (no quotes handling)
2function parseCsvLine(line, headers) {
3 const values = line.split(",").map(v => v.trim());
4 const obj = {};
5 headers.forEach((h, i) => obj[h] = values[i] ?? null);
6 return obj;
7}
8
9const headers = ["name", "age", "city"];
10const line = " Alice , 30 , New York ";
11console.log(parseCsvLine(line, headers));
12// { name: "Alice", age: "30", city: "New York" }
- Questo metodo funziona per i CSV semplici, ma tieni presente che non può gestire casi in cui una virgola si trova all'interno di un campo tra virgolette.
Errori comuni
Ci sono alcune specifiche e comportamenti facilmente trascurabili nella gestione delle stringhe JavaScript. Per evitare bug inaspettati, è importante tenere a mente i seguenti punti.
- Usare
new String()può portare a risultati errati con il controllo del tipo o i confronti. Nella maggior parte dei casi, i tipi di stringa primitivi sono sufficienti. - In Unicode, un singolo carattere visibile può essere composto da più unità di codice. Pertanto, il valore restituito da
lengthpotrebbe non corrispondere al numero reale di caratteri visualizzati. - Quando incorpori input utente in un'espressione regolare, effettua sempre prima l'escape.
String.prototype.replace()sostituisce solo la prima corrispondenza di default. Se vuoi sostituire tutte le occorrenze, usa il flag/gnella tua espressione regolare.- Le stringhe sono immutabili, quindi le operazioni restituiscono sempre una nuova stringa. È importante assegnare sempre il valore restituito.
Riepilogo
Anche se le stringhe JavaScript possono sembrare semplici, è importante comprenderne le caratteristiche in relazione a Unicode e all'immutabilità. Imparando le basi, puoi migliorare notevolmente l'affidabilità e la leggibilità del tuo processamento di stringhe.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.