`String`-objekt
Denne artikkelen forklarer String-objektet.
Forklaringen dekker alt fra grunnleggende til avanserte teknikker, inkludert fallgruver knyttet til Unicode og regulære uttrykk, steg for steg på en lettfattelig måte.
YouTube Video
String-objekt
Strenger i JavaScript er en av de mest brukte typene i daglig utvikling.
Forskjellen mellom primitive strenger og String-objekter
Primitive strenger (som "hello") oppfører seg annerledes enn innpakkede objekter som new String("hello"). Vanligvis bør du bruke primitive strenger, og det er sjelden nødvendig å bruke objektformen.
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
- Denne koden viser forskjellen i type mellom en primitiv streng og en wrapper, samt hvordan de oppfører seg ved streng sammenligning. I de fleste tilfeller bør du unngå å bruke
new String()og heller bruke primitive strenger.
Måter å lage strenger på (litteraler og templatlitteraler)
Templatlitteraler er nyttige for å sette inn variabler og skrive flersidige strenger. Du kan intuitivt sette inn variabler og evaluere uttrykk.
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"
- Templatlitteraler er svært lesbare og ideelle for å bygge komplekse strenger, inkludert flersidige strenger.
Vanlige metoder (søk og uthenting av understrenger)
String-objektet har mange grunnleggende metoder.
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"
sliceogsubstringligner på hverandre, men håndterer negative indekser forskjellig.slicetolker negative verdier som posisjoner fra slutten. Vær tydelig på hvilken du skal bruke.
Splitting og sammenslåing (split / join)
Det er vanlig å splitte en streng til et array for behandling, og deretter sette det sammen igjen.
1const csv = "red,green,blue";
2const arr = csv.split(","); // ["red","green","blue"]
3
4console.log(arr);
5console.log(arr.join(" | ")); // "red | green | blue"
- Et vanlig mønster er å bruke
splitfor å dele opp en streng, behandle den resulterende listen medmapellerfilter, og deretter brukejoinfor å sette den sammen igjen.
Erstatning og regulære uttrykk
replace erstatter bare det første treffet. Hvis du vil erstatte alle treff, bruk g-flagget med et regulært uttrykk. Ved å sende en funksjon som erstatning, kan du også utføre dynamiske utskiftninger.
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"
- Med dynamisk erstatning ved hjelp av en funksjon, kan du skrive kode som analyserer og transformerer treff på en enkel måte.
Endring av store/små bokstaver og normalisering
For flerspråklig støtte og sammenligning er det, i tillegg til toLowerCase og toUpperCase, også viktig med Unicode-normalisering (normalize). Dette er spesielt nødvendig når du sammenligner aksenterte tegn.
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
- Ulike Unicode-representasjoner, som ligaturer og kombinerende tegn, vil ikke være like som de er, så bruk
normalize()før du sammenligner.
Unicode og kodepunkter (håndtering av surrogatpar)
JavaScript-strenger er sekvenser av UTF-16-kodeenheter, så noen tegn som emoji kan oppta to kodeenheter for ett enkelt tegn. For å håndtere reelle tegnenheter, bruk Array.from, spread-operatøren eller 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));lengthreturnerer antall kodeenheter, så du får kanskje ikke forventet antall med emoji eller ligaturer.for...ofogArray.fromhåndterer omtrent det som vises på skjermen (grafemklaser), men hvis du trenger full støtte for grafemer, bør du bruke et spesialisert bibliotek.
Trygg bruk av regulære uttrykk (ved håndtering av brukerinput)
Hvis du glemmer å escaper brukerinput når du setter det inn i et regulært uttrykk, kan det føre til uventet oppførsel og sårbarheter. Escape alltid brukerinput før du bruker det i et mønster.
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"
- Ikke bruk brukerstrenger direkte i regulære uttrykk; escape dem alltid før du lager regexen.
Ytelsestips: Sammenkobling og maler
Når du sammenkobler mange små strenger i rekkefølge, kan det være mer effektivt å legge dem i et array og bruke join. På den annen side er malstrenger svært lesbare og raske nok i de fleste tilfeller.
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("");- Moderne JavaScript-motorer er svært optimaliserte, så du trenger ikke bekymre deg for ytelsen ved et lite antall sammenkoblinger. Men hvis du må sammenkoble titusenvis av ganger, kan det lønne seg å bruke
join.
Nyttige praktiske teknikker: Padding, trim og repeat
trim, padStart, padEnd og repeat er praktiske metoder som er spesielt nyttige i daglig strengbehandling. De brukes ofte i praktiske situasjoner som formatering av inntastingsverdier eller standardisering av utdataformater.
1console.log(" hello ".trim()); // "hello"
2console.log("5".padStart(3, "0")); // "005"
3console.log("x".repeat(5)); // "xxxxx"
- Disse metodene kan brukes til å normalisere skjemainput eller generere utdata med fast bredde.
Strengsammenligning (lokalisert sammenligning)
localeCompare er effektiv for å sammenligne strenger etter ordboksrekkefølge for ulike språk. Du kan angi språk og følsomhetsalternativer (for eksempel store/små bokstaver).
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
- For internasjonaliserte sammenligninger bruk
localeCompareog angi riktig språk og alternativer.
Praktisk eksempel: Konvertere en CSV-rad til et objekt (praktisk arbeidsflyt)
Et vanlig bruksområde er å analysere en enkelt CSV-rad til et objekt ved hjelp av en kombinasjon av split, trim og map. For felter med anførselstegn eller komplekse CSV-filer, bruk en dedikert CSV-parser.
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" }
- Denne metoden fungerer for enkel CSV, men vær oppmerksom på at den ikke håndterer tilfeller der en komma finnes inne i et felt med anførselstegn.
Vanlige fallgruver
Det finnes noen lett oversette spesifikasjoner og oppførsel i JavaScript-strenghåndtering. For å unngå uventede feil er det viktig å huske på følgende punkter.
- Å bruke
new String()kan føre til feil resultater ved typesjekk eller sammenligninger. I de fleste tilfeller er primitive strengtyper tilstrekkelige. - I Unicode kan et enkelt synlig tegn bestå av flere kodeenheter. Derfor kan verdien som returneres av
lengthavvike fra det faktiske antallet viste tegn. - Når du setter inn brukerinput i et regulært uttrykk, må du alltid escape det først.
String.prototype.replace()erstatter kun det første treffet som standard. Hvis du vil erstatte alle forekomster, bruk flagget/gi ditt regulære uttrykk.- Strenger er uforanderlige, så operasjoner returnerer alltid en ny streng. Det er viktig å alltid tildele den returnerte verdien.
Sammendrag
Selv om JavaScript-strenger kan virke enkle, er det viktig å forstå deres egenskaper når det gjelder Unicode og uforanderlighet. Ved å beherske det grunnleggende kan du betraktelig forbedre påliteligheten og lesbarheten i strengbehandlingen din.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.