Stringi (czyli inaczej mówiąc ciągi znaków) są obok liczb najczęściej wykorzystywanym typem danych w JavaScript. W poprzednich lekcjach tego kursu pojawiały się już kilkukrotnie szczątkowe informacje na ich temat, jednak do tej pory nie doczekały się one dokładniejszego opisu. Ta część kursu Java Script zawiera dokładne informacje jak używać stringów w JS.

Łączenie stringów ze sobą

Ciągi znaków używane w skryptach muszą być ujęte w cudzysłowy, albo w apostrofy (pojedyncze cudzysłowy). Można je też przypisywać do zmiennych, tak jak wartości innych typów. Możliwe jest też łączenie kilku stringów w jeden – w tym celu należy użyć znaku plus (“+”):

var imie = 'Daniel';
var powitanie = 'Witaj, ' + imie + '!';

Innym sposobem łączenia stringów w jeden jest skorzystanie z metody concat() – zwraca ona ciąg znaków składający się z połączonych: obiektu na którym wywołana została ta metoda, oraz wszystkich przekazanych parametrów. Metoda ta może przyjąć dowolną ilość parametrów.

var s1 = 'a';
var s2 = 'b';
var s3 = 'c';
var s = s1.concat(s2, s3); // 'abc'

Porównywanie stringów

Wartości typu string można też porównywać ze sobą. Służą do tego standardowe operatory porównania: ==, ===, !=, !==, <, <=, >, >=. Porównanie dokonywane jest wg porządku alfabetycznego. Więcej informacji na temat tych operatorów znajduje się w lekcji opisującej operatory porównania i relacyjne – możesz tam zajrzeć jeżeli potrzebujesz sobie przypomnieć informacje na ich temat.

Przy okazji przypominam, że jeżeli liczby są przechowywane jako stringi, to przed wykonaniem niektórych operacji na nich (np. dodawania) trzeba dokonać zmiany typu na liczbę. Do tego celu wykorzystuje się funkcje parseInt() (konwersja na liczbę całkowitą) i parseFloat() (konwersja na liczbę zmiennoprzecinkową).

Pobieranie ilości znaków (długości stringa)

Do pobierania ilości znaków w stringu, czyli jego długości, służy właściwość length:

function WyswietlDlugosc(s)
{
    alert('Dlugosc: ' + s.length);
}

Operacje na pojedynczych znakach

Aby pobrać pojedynczy znak z ciągu znaków, można użyć jednej z opisanych dalej funkcji pobierających fragment ciągu znaków. Lepiej jest jednak użyć funkcji dedykowanej do tego celu, czyli charAt(). Jako parametr podaje się indeks znaku (od zero do N, gdzie N to długość stringu minus jeden). Poniższy przykład pokazuje jak rozdzielić przecinkami poszczególne znaki w stringu:

function RozdzielPrzecinkami(str)
{
    // sprawdz czy string jest pusty
    if (str.length == 0)
        return '';
    
    // na poczatku wynik to pierwszy znak
    var wynik = str.charAt(0);
    
    // dolacz pozostale znaki, poprzedzajac je przecinkiem
    for (n = 1; n < str.length; ++n)
        wynik += ',' + str.charAt(n);
    
    // zwroc wynik
    return wynik;
}

Czasami może być też przydatna możliwość odczytania kodu znaku. Do tego celu służy metoda charCodeAt() – zwraca ona kod znaku (w standardzie Unicode) znajdującego się na podanej pozycji.

Istnieje też możliwość zbudowania stringu poprzez podanie kodów kolejnych znaków – do tego celu służy funkcja statyczna (wywoływana na klasie, a nie na jej obiektach) – String.fromCharCode(). Jako parametry przekazuje się jej listę kodów znaków, z których ma ona utworzyć gotowy string.

Poniższy przykład pokazuje jak zwiększyć kody wszystkich znaków w stringu o jeden, wykorzystując do tego ostatnie dwie funkcje:

function NastepneZnaki(str)
{
    // zmienna przechowujaca wynik
    var wynik = '';
    
    // utworzenie wynikowego stringu
    for (n = 0; n < str.length; ++n)
    {
        // pobranie kody znaku
        var kod_znaku = str.charCodeAt(n);
        // dolaczenie znaku o kolejnym kodzie
        wynik += String.fromCharCode(kod_znaku + 1);
    }
    
    // zwrocenie wyniku
    return wynik;
}

Zmiana wielkości znaków

Klasa String udostępnia też metody do zmiany wielkości znaków na małe lub na duże. Do zmiany znaków ma małe służy metoda toLowerCase(), a do zmiany na duże – metoda toUpperCase(). Metody te zwracają string w którym wszystkie znaki są zamienione na małe lub na duże (w zależności od użytej metody).

Dostępne są także metody toLocaleLowerCase() i toLocaleUpperCase – one przy konwersji znaków na małe/duże uwzględniają dodatkowo ustawienia narodowe na komputerze gdzie jest uruchamiany skrypt.

Wyszukiwanie podciągów

W praktyce często zachodzi potrzeba odszukania określonego podciągu w stringu, ew. sprawdzenie czy dany podciąg w nim istnieje. Do tego celu najlepiej jest wykorzystać gotową metodę indexOf() – zwraca ona pozycję w stringu, pod którą znajduje się przekazany jako parametr ciąg znaków (a dokładnie jego pierwszy znak). W przypadku gdy nie uda się go odnaleźć, zwracana jest wartość -1. Poniższy przykład pokazuje jak sprawdzić czy w stringu znajduje się znak minus:

if (str.indexOf('-') >= 0)
    // wykonaj jakies operacje

Do funkcji indexOf() można także przekazać drugi parametr – indeks znaku od którego powinno się rozpocząć poszukiwanie. Jest on przydatny w sytuacji gdy trzeba przeszukać ciąg znaków pod kątem wszystkich wystąpień określonego podciągu. Przykładowo tak można policzyć ilość minusów w stringu:

function IleMinusow(str)
{
    // zmienna przechowujaca wynik
    var wynik = 0;
    
    // zmienne przekazujaca pozycje od ktorej wyszukiwac
    // zapisujemy w niej wynik pierwszego wyszukiwania
    var pozycja = str.indexOf('-');
    
    // petla wykonujaca sie dopoki znajdowane sa minusy
    while (pozycja >= 0)
    {
        // zwieksz licznik minusow
        ++wynik;
        // odszukaj kolejny minus
        pozycja = str.indexOf('-', pozycja + 1);
    }
    
    // zwrocenie wyniku
    return wynik;
}

Obok funkcji indexOf() dostępna jest jeszcze druga metoda do wyszukiwania podciągów: lastIndexOf(). Szuka ona podciągu rozpoczynając od końca stringu, (indexOf() rozpoczyna od początku). Posiada ona identyczne parametry jak indexOf() – podciąg do odszukania i (opcjonalnie) indeks od którego rozpocząć wyszukiwanie. Wynik zwracany jest też podobnie – indeks pierwszego znaku znalezionego podciągu lub -1 jeżeli nic nie znaleziono.

Zamiana podciągów na inne

Inną popularną operacją na stringach, oprócz wyszukiwania podciągów, jest podmiana wyszukanych podciągów na inne. Klasa String udostępnia odpowiednią metodę do tego celu – replace(). Metoda ta przyjmuje dwa parametry – wyszukiwany ciąg znaków oraz ciąg znaków na który on ma zostać zamieniony. Przy takim sposobie wywołania funkcja ta zamieni tylko pierwsze wystąpienie podanego ciągu znaków, co zazwyczaj nie jest pożądane (zwykle chcemy zamienić wszystkie wystąpienia). Aby zamienić wszystkie wystąpienia szukanego ciągu znaków na inny ciąg znaków, trzeba napisać odpowiednią pętlę (przykład poniżej). Ten sposób nie jest jednak najlepszy – lepiej użyć wyrażeń regularnych, które będą opisane w jednej z kolejnych lekcji.

function ZamienWszystko(str, co, na_co)
{
    while (true)
    {
        var str2 = str.replace(co, na_co);
        if (str2 == str)
            return str;
        else
            str = str2;
    }
}

Podany powyżej sposób użycia metody replace() jest najprostszym z możliwych, gdyż ta metoda posiada większe możliwości. Jedną z nich jest fakt że znaki dolara (“$”) podane wewnątrz drugiego parametru mają specjalne znaczenie. Ich znaczenie jest zależne od znaku który zostanie umieszczony po nich:

  • $$ – zostanie zamienione na pojedynczy znak dolara;
  • $& – zostanie zamienione na wyszukany ciąg znaków (pierwszy parametr funkcji);
  • $` – (dolar i odwrotny apostrof) – zostanie zamienione na ciąg znaków który znajduje się przed odnalezionym ciągiem znaków;
  • $' – (dolar i zwykły apostrof) – zostanie zamienione na ciąg znaków który znajduje się za odnalezionym ciągiem znaków.

Oprócz tego można użyć jeszcze $n i $nn – (dolar i jedna lub dwie cyfry) – te dwa specjalne ciągi mają znaczenie jeżeli pierwszym parametrem przekazanym do funkcji replace() było wyrażenie regularne. Ich zastosowanie dokładniej omówię w jednej z kolejnych lekcji tego kursu, poświęconej zaawansowanym operacjom na stringach. Tam też omówię jeszcze jedną możliwość którą daje metoda replace() – jako drugi parametr można do niej przekazać funkcję, która będzie wywołana po każdym odnalezieniu szukanego ciągu znaków.

Pobieranie podciągów

Następną operację którą można wykonać na stringach jest pobranie podciągu. Do tego celu służą dwie metody: slice() i substring(). Obydwie przyjmują dwa parametry: indeks pierwszego znaku zwracanego podciągu, oraz indeks znaku znajdującego się za ostatnim znakiem zwracanego podciągu. Można też wywołać te metody podając tylko jeden parametr – w takim przypadku zwrócony zostanie podciąg od podanego znaku do końca stringa:

var str = 'abcdef';
 
var str2 = str.substring(1, 4); // 'bcd'
var str3 = str.substring(1); // 'bcdef'
 
var str4 = str.slice(1, 4); // 'bcd'
var str5 = str.slice(1); // 'bcdef'

Różnica pomiędzy tymi funkcjami jest jedynie w przypadku gdy poda się jako parametry wartości spoza zakresu [0, ilosc_znakow). W takim przypadku funkcja substring() zamieni je – ujemne na zero, a te większe od długości stringu na (ilosc_znakow – 1). Funkcja slice() przyjmie natomiast że liczby ujemne są to indeksy znaków liczone od końca stringu:

var str = 'abcdef';
 
var str2 = str.substring(-1, 3); // 'abc'
var str3 = str.slice(-4, -1); // 'cde'

Podział na tokeny

Ostatnią operacją na stringach którą opiszę w tej części kursu jest podział na tokeny. Jest to operacja polegająca na podziale stringu na części w miejscach gdzie znajduje się np. określony znak, przykładowo średnik. To wykonania tej operacji najlepiej jest wykorzystać gotową metodę split(), do której jako parametr przekazuje się używany separator. Zwraca ona tablicę, której poszczególnymi elementami są rozdzielone podciągi (tokeny):

var str = 'Ania,Ola,Kasia,Magda';
var imiona = str.split(',');
// imiona = [ 'Ania', 'Ola', 'Kasia', 'Magda' ];

Funkcja split() akceptuje też drugi parametr – maksymalną ilość elementów na które może być podzielony string. Jeżeli się go poda, funkcja zwróci tablicę zawierającą najwyżej tyle elementów, ile wynosi ten parametr (pomimo że string może dać się podzielić na większą ich liczbę). W przypadku podania zera zwrócona zostanie pusta tablica.

Funkcja split() może jako pierwszy parametr przyjąć też wyrażenie regularne. Ten sposób wywołania tej funkcji opiszę w dalszej części tego kursu, poświęconej zaawansowanym operacjom na stringach. Tam też omówię metody pominięte tutaj, a które operują na wyrażeniach regularnych: match() i search().