Menu

Stringi i template literals w JavaScript

Jak działają stringi w JavaScript: cudzysłowy, backticki, interpolacja, tekst wielowierszowy i metody, po które naprawdę sięgasz na co dzień.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Trzy sposoby zapisu stringa

JavaScript daje ci trzy ograniczniki stringów. Dwa są wymienne, trzeci potrafi więcej.

Apostrofy i cudzysłowy dają identyczne stringi: wybierz jeden styl i się go trzymaj (większość nowoczesnych projektów domyślnie używa apostrofów albo zostawia decyzję formaterowi). Backticki tworzą template literal i tu robi się ciekawie: pozwalają na interpolację i obejmują wiele linii.

Pod spodem wszystkie trzy tworzą ten sam prymitywny typ string. Ogranicznik to tylko kwestia składni.

Sekwencje ucieczki i cudzysłowy w środku

Wewnątrz stringa ukośnik wsteczny zaczyna sekwencję ucieczki. Najczęstsze to \n (nowa linia), \t (tabulator), \\ (dosłowny ukośnik wsteczny) oraz \" / \' do wstawienia tego samego cudzysłowu, którym string otwarto:

Większości znaków ucieczki unikniesz, wybierając drugi rodzaj cudzysłowu: 'She said "hi" and left.' nie potrzebuje żadnego ukośnika. Pragmatyzm ponad dogmaty.

Template literals: supermoc backticków

Template literal robi dwie rzeczy, których nie potrafią zwykłe stringi. Po pierwsze, interpoluje wyrażenia przez ${...}:

Wszystko wewnątrz ${...} to wyrażenie JavaScript, a nie tylko nazwa zmiennej. Arytmetyka, wywołania funkcji, operatory trójargumentowe, a nawet inne template literals, wszystko wolno:

Po drugie, template literals obejmują wiele linii bez \n:

Znaki nowej linii w kodzie źródłowym stają się znakami nowej linii w stringu. Przy wszystkim, co jest dłuższe od krótkiej etykiety, backticki to prawie zawsze dobry wybór.

Interpolacja wygrywa z konkatenacją

Zanim pojawiły się template literals, jedynym sposobem na zbudowanie dynamicznego stringa był operator +:

Obie wersje dają identyczny wynik. Template literal czyta się jak zdanie, które buduje, a wersja z + zmusza cię do pilnowania cudzysłowów, spacji i operatorów konkatenacji. Używaj + tylko wtedy, gdy doklejasz coś małego do istniejącego stringa. Przy czymkolwiek dłuższym sięgaj po backticki.

Stringi są niemutowalne

Każda metoda, która wygląda, jakby zmieniała string, w rzeczywistości zwraca nowy:

Jeśli chcesz zachować zmianę, musisz gdzieś przypisać wynik. To pułapka dla początkujących, którzy piszą s.replace("a", "b") i oczekują, że s się zmieni. Nie zmieni się. Stringi w JavaScript są jak liczby: samej wartości nie da się zmienić, można tylko skierować zmienną na nową wartość.

Metody stringów, których naprawdę używasz

Pełne API stringów jest duże. Oto garść metod, po które sięgasz codziennie:

Kilka rzeczy, które warto zapamiętać:

  • length to właściwość, a nie metoda: bez nawiasów.
  • replace ze zwykłym stringiem zamienia tylko pierwsze wystąpienie. Żeby zamienić wszystkie, użyj replaceAll albo wyrażenia regularnego z flagą g.
  • slice(start, end) przyjmuje przedział prawostronnie otwarty: znak na pozycji end nie jest wliczany.
  • Ujemne indeksy w slice liczą się od końca: s.slice(-3) daje ostatnie trzy znaki.

Indeksowanie i przechodzenie po znakach

Stringi zachowują się jak tablice znaków tylko do odczytu. Możesz odwoływać się do nich przez indeks i po nich iterować, ale nie możesz przypisać wartości na danej pozycji:

for...of iteruje po punktach kodowych (code points), co poprawnie obsługuje większość Unicode. Indeksy (s[i]) iterują po jednostkach kodu UTF-16, co potrafi przeciąć na pół emoji i inne znaki spoza BMP. Przy zwykłym tekście oba sposoby są w porządku. Przy treściach wpisywanych przez użytkowników wybierz for...of albo [...s].

Tagged template literals

Jest jeszcze jedna forma, którą warto znać, nawet jeśli rzadko ją piszesz. Otagowany (tagged) template literal wywołuje funkcję, przekazując jej osobno statyczne kawałki stringa i wstawione wartości:

Funkcja tagu decyduje, jak wygląda końcowy string: może escapować HTML, bezpiecznie budować SQL, kompilować CSS albo parsować GraphQL. Ten wzorzec zobaczysz w bibliotekach (styled-components, graphql-tag, lit-html) znacznie częściej, niż sam go napiszesz. Ale gdy potrzebujesz własnego przetwarzania stringów, tagi są najczystszym narzędziem.

Typowe pułapki

Krótka lista rzeczy, na których ludzie się potykają:

  • Zapominanie o przypisaniu wyniku metody. Samo s.trim() nic nie robi.
  • Łączenie liczby ze stringiem przez +. "Age: " + 30 + 5 to "Age: 305", a nie "Age: 35". Template literals omijają ten problem: `Age: ${30 + 5}`.
  • Mylenie == z porównywaniem stringów. Równości przyjrzymy się dokładnie później, ale "1" == 1 to true, a "1" === 1 to false. Wybieraj ===.
  • Założenie, że length to liczba znaków. Dla emoji i innych znaków z par zastępczych "".length to 2, a nie 1. Użyj [..."".length] albo Array.from(s).length, gdy potrzebujesz znaków widzianych przez użytkownika.

Dalej: Number i BigInt

Stringi to jeden typ prymitywny, liczby to drugi, a system liczbowy JavaScript ma własne dziwactwa: jeden typ Number dla liczb całkowitych i zmiennoprzecinkowych oraz BigInt na wypadek, gdy to nie wystarcza. O tym na następnej stronie.

Najczęściej zadawane pytania

Czym różnią się cudzysłowy od backticków w JavaScript?

Apostrofy (') i cudzysłowy (") tworzą zwykłe stringi i można ich używać zamiennie. Backticki (`) tworzą template literals, które obsługują interpolację przez ${...} i obejmują wiele linii bez znaków ucieczki. Sięgaj po backticki zawsze, gdy wstawiasz zmienną albo piszesz tekst w kilku liniach.

Jak wstawić zmienną do stringa w JavaScript?

Użyj template literal: otocz tekst backtickami i umieść wyrażenie w ${...}. Na przykład `Hello, ${name}!` oblicza name i wkleja wynik do tekstu. W środku może stać dowolne wyrażenie: ${a + b}, ${user.name.toUpperCase()}, a nawet zagnieżdżone template literals.

Czy stringi w JavaScript są niemutowalne?

Tak. Każda metoda stringa (toUpperCase, slice, replace i tak dalej) zwraca nowy string, zamiast zmieniać oryginał. Jeśli napiszesz s.toUpperCase() i nigdzie nie przypiszesz wyniku, nic się nie zmieni. To ten sam model co w przypadku stringów w Pythonie czy Javie.

Czym są tagged template literals?

Tagged template literal wywołuje funkcję, przekazując jej osobno kawałki tekstu szablonu i wstawione wartości: tag`Hello, ${name}` wywołuje tag(["Hello, ", ""], name). Biblioteki takie jak styled-components i graphql-tag używają tagów, żeby przetworzyć albo przekształcić szablon przed zwróceniem wyniku.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ