Operatory to specjalne symbole służące do wykonywania operacji na danych, takich jak liczby czy teksty zapisane w zmiennych. Wyrażenie to kombinacja wartości, zmiennych i operatorów, która jest obliczana (ewaluowana) do jednej wartości. Innymi słowy, wyrażenie z użyciem operatorów pozwala nam uzyskać nową wartość na podstawie istniejących danych. Na przykład, w wyrażeniu c = a + b; używamy operatora + do dodania wartości zmiennych a i b, a wynik przypisujemy za pomocą operatora = do zmiennej c. W wyniku wykonania takiej instrukcji zmienna c będzie zawierać sumę wartości a i b. Poniżej przedstawiono ten przykład w kodzie:
let a = 5; let b = 3;
let c = a + b; // dodajemy wartości a i b, wynik (8) przypisujemy do c
console.log(c); // wypisze 8, ponieważ 5 + 3 = 8
W powyższym kodzie + i = to operatory, a cała instrukcja c = a + b jest wyrażeniem przypisania, które najpierw oblicza sumę, a następnie przypisuje wynik do zmiennej c. Zmienna c przyjmie nową wartość w wyniku tej operacji.
JavaScript udostępnia wiele operatorów, które możemy podzielić na różne kategorie w zależności od ich przeznaczenia. Poniżej omówimy najważniejsze rodzaje operatorów oraz to, jak działają one na zmiennych i wartościach.
- Operatory arytmetyczne (matematyczne): służą do wykonywania podstawowych operacji matematycznych na liczbach.
+(dodawanie) – sumuje dwie wartości. Może także służyć do łączenia tekstów (konkatenacji stringów).-(odejmowanie) – odejmuje drugą wartość od pierwszej.*(mnożenie) – mnoży dwie wartości./(dzielenie) – dzieli pierwszą wartość przez drugą.%(modulo) – zwraca resztę z dzielenia pierwszej wartości przez drugą (np.7 % 3daje1, bo 7 dzielone przez 3 ma resztę 1).**(potęgowanie) – podnosi pierwszą wartość do potęgi drugiej (np.2 ** 3to 2 do potęgi 3, czyli 8).
Przykłady użycia operatorów arytmetycznych:
let x = 10;
let y = 4;
console.log(x + y); // 14 (dodawanie 10 + 4)
console.log(x - y); // 6 (odejmowanie 10 - 4)
console.log(x * y); // 40 (mnożenie 10 * 4)
console.log(x / y); // 2.5 (dzielenie 10 / 4)
console.log(x % y); // 2 (reszta z dzielenia 10 / 4, ponieważ 4*2 = 8, reszta 2)
console.log(2 ** 3); // 8 (potęgowanie, 2 do potęgi 3)
W powyższych przykładach wykorzystano zmienne x i y do demonstracji podstawowych działań arytmetycznych. Warto zauważyć, że operatory +, -, *, / działają podobnie jak w matematyce. Operator % (modulo) często bywa użyteczny do sprawdzania podzielności liczby (gdy a % b == 0, to a dzieli się przez b bez reszty). Z kolei operator ** jest wygodnym sposobem zapisu potęgowania (zamiast funkcji Math.pow()).
- Operatory przypisania: służą do przypisywania wartości zmiennym. Najprostszy operator przypisania to znak równości
=używany już w powyższych przykładach. Lewa strona operatora=wskazuje zmienną, której chcemy nadać wartość, a prawa strona to wyrażenie, które zostanie obliczone, a jego wynik przypisany. Oprócz podstawowego=, JavaScript oferuje skrócone operatory przypisania, które łączą operację arytmetyczną z przypisaniem:x = value– przypisuje zmiennejxwartośćvalue.x += value– dodajevaluedo aktualnej wartościxi zapisuje wynik ponownie wx(skrót odx = x + value).x -= value– odejmujevalueod aktualnej wartościx(skrót odx = x - value).x *= value– mnoży aktualną wartośćxprzezvalue(skrót odx = x * value).x /= value– dzieli aktualną wartośćxprzezvalue(skrót odx = x / value).x %= value– zastępujexresztą z dzieleniaxprzezvalue(skrót odx = x % value).
Poniższy fragment kodu ilustruje działanie operatorów przypisania:
let liczba = 7;
console.log(liczba); // 7 (początkowa wartość) liczba = 10;
console.log(liczba); // 10 (po przypisaniu nowej wartości za pomocą =) liczba += 5;
console.log(liczba); // 15 (dodano 5, więc 10 + 5) liczba *= 2;
console.log(liczba); // 30 (pomnożono przez 2, więc 15 * 2) liczba -= 10;
console.log(liczba); // 20 (odjęto 10, więc 30 - 10)
W kodzie powyżej zmienna liczba najpierw otrzymuje wartość 7. Następnie kolejno przypisujemy jej nowe wartości, pokazując przy tym użycie skróconych operatorów przypisania. Po wykonaniu liczba += 5 zmienna zwiększa swoją wartość o 5 (z 10 na 15). Operator *= podwaja wartość zmiennej (15 staje się 30), a operator -= zmniejsza wartość o 10 (30 staje się 20).
- Operatory inkrementacji i dekrementacji: są to specjalne operatory arytmetyczne służące do zwiększania lub zmniejszania wartości zmiennej o 1. Operator inkrementacji
++zwiększa wartość zmiennej o jeden, a dekrementacji--zmniejsza o jeden. Istnieją dwa warianty tych operatorów:- Post-inkrementacja (
x++) – zwraca bieżącą wartośćx, a następnie zwiększaxo 1.Pre-inkrementacja (++x) – najpierw zwiększa wartośćxo 1, a następnie zwraca nową wartość. (Analogicznie dla dekrementacji:x--zwraca najpierw starą wartość i potem zmniejsza, a--xzmniejsza najpierw i zwraca zmniejszoną).
Różnicę między tymi wariantami najlepiej zrozumieć na przykładzie:
- Post-inkrementacja (
let i = 5;
console.log(i++); // wypisuje 5, *najpierw* zwraca starą wartość, potem i=6
console.log(i); // wypisuje 6, zmienna i została zwiększona w poprzedniej operacji
console.log(++i); // wypisuje 7, bo najpierw inkrementuje (6->7), potem zwraca 7
console.log(i); // wypisuje 7, i pozostało zwiększone
W powyższym kodzie początkowo i wynosi 5. Gdy wykonujemy console.log(i++), zostanie wyświetlone 5 (wartość przed inkrementacją), ale wewnętrznie i zwiększy się do 6. Następne wywołanie console.log(i) potwierdza, że i jest już równe 6. Natomiast console.log(++i) od razu zwiększa i do 7 i zwraca tę nową wartość, więc wypisuje 7. Ostatecznie i ma wartość 7. Warto używać pre- lub post-inkrementacji świadomie, zwłaszcza wewnątrz bardziej złożonych wyrażeń, aby uniknąć pomyłek.
- Operatory porównania (relacyjne): umożliwiają porównywanie dwóch wartości. Wynikiem wyrażenia porównania jest zawsze wartość logiczna
true(prawda) lubfalse(fałsz). Operatory te są podstawą do podejmowania decyzji w programie (np. w instrukcjach warunkowych). Do operatorów porównania należą:==– porównanie luźne (równość wartości): zwracatrue, jeśli wartości po obu stronach są sobie równe po dokonaniu konwersji typu. Np.5 == "5"zwrócitrue, bo string „5” zostanie skonwertowany na liczbę 5, która równa się 5.===– porównanie ścisłe (identyczność): zwracatruetylko, jeśli operandy są równe i mają ten sam typ. Np.5 === "5"dafalse, ponieważ mimo że wartości numeryczne są równe, to porównywane są różne typy (numbervsstring). Z kolei5 === 5datrue(ta sama wartość i typ).!=– operator „różne” (negacja luźnego porównania): zwracatrue, jeśli dwie wartości nie są sobie równe (po ewentualnej konwersji typu). Np.5 != "5"dafalse(bo po konwersji „5” na 5 wartości są równe, więc nie są różne).!==– operator „ściśle różne”: zwracatrue, jeśli wartości albo ich typy są różne (brak identyczności). Np.5 !== "5"datrue(bo typy są różne, więc wartości nie są identyczne), a5 !== 5dafalse(bo zarówno wartość, jak i typ są takie same).<– mniejszy niż:x < yjesttrue, jeślixjest mniejsze ody.<=– mniejszy lub równy:x <= yjesttrue, jeślixjest mniejsze lub równey.>– większy niż:x > yjesttrue, jeślixjest większe ody.>=– większy lub równy:x >= yjesttrue, jeślixjest większe lub równey.
Przykłady zastosowania operatorów porównania:
console.log(10 > 5); // true (10 jest większe od 5)
console.log(10 < 5); // false (10 nie jest mniejsze od 5)
console.log(5 == "5"); // true (równe po konwersji typu string "5" -> number 5)
console.log(5 === "5"); // false (różny typ, porównanie ścisłe nie przejdzie)
console.log(7 != "7"); // false (7 i "7" po konwersji uznane za równe, więc "nie równe" jest fałszem)
console.log(7 !== "7"); // true (7 jako liczba i "7" jako tekst nie są identyczne)
console.log(8 >= 8); // true (8 jest równe 8, więc spełnia warunek ">= 8")
console.log(9 <= 8); // false (9 nie jest mniejsze ani równe 8)
Gdy korzystamy z operatorów porównania, warto pamiętać o różnicy między == a ===. W JavaScript operator podwójnego równości == dokonuje automatycznej konwersji typów, co czasem może prowadzić do nieintuicyjnych rezultatów dla mniej oczywistych porównań (np. 0 == false jest true, ponieważ false zostanie skonwertowane na 0). Dlatego w nowoczesnym JavaScript zaleca się stosowanie raczej operatorów ścisłej równości === i ścisłej różności !== – są one bardziej przewidywalne, bo nie wykonują ukrytego rzutowania typów.
- Operatory logiczne: pozwalają łączyć wyrażenia logiczne (porównania) i operować na wartościach boolean (
true/false). Najważniejsze z nich to:&&(logiczne i, ang. AND) – zwracatruewtedy i tylko wtedy, gdy oba warunki/operandy są prawdziwe. Jeśli chociaż jeden jest fałszywy, wynik będziefalse.||(logicjne lub, ang. OR) – zwracatrue, gdy przynajmniej jeden z warunków jest spełniony (prawdziwy). Wynik jestfalsetylko, gdy oba warunki są fałszywe.!(logicza negacja, ang. NOT) – zwraca wartość przeciwną do operandu logicznego: ztruerobifalse, zfalserobitrue. Używany do odwracania warunków.
(X > 0 && X < 10). Z kolei warunek „liczba jest parzysta lub większa od 100″ zapiszemy jako(liczba % 2 == 0 || liczba > 100). Przykłady działania operatorów logicznych:
let x = 5;
let y = 12;
console.log(x > 0 && y > 0); // true (oba warunki są prawdziwe: x>0 i y>0)
console.log(x > 10 && y > 0); // false (pierwszy warunek x>10 jest fałszywy)
console.log(x % 2 == 1 || y % 2 == 1); // true (x jest nieparzyste LUB y jest nieparzyste; tu x%2==1 jest true)
console.log(!(x > 0)); // false (negacja true daje false; x > 0 było true, więc !true -> false)
W powyższym kodzie pokazano kilka kombinacji: użycie && sprawia, że cały warunek jest spełniony tylko, jeśli wszystkie części składowe są spełnione (przykład z x > 0 && y > 0). Operator || zwraca true, jeśli spełniony jest przynajmniej jeden z warunków (sprawdziliśmy, czy któraś z liczb x lub y jest nieparzysta). Operator ! odwraca wartość logiczną warunku (jeżeli x > 0 jest prawdą, to !(x > 0) będzie fałszem).
Warto wspomnieć, że operatory logiczne && i || podlegają mechanizmowi leniwej ewaluacji (ang. short-circuiting). Oznacza to, że w wyrażeniu logicznym JavaScript może pominąć sprawdzanie drugiej części, jeśli wynik można jednoznacznie określić na podstawie pierwszej. Na przykład, w wyrażeniu (warunek1 && warunek2) jeśli warunek1 okaże się fałszywy, to całość i tak będzie fałszywa – interpreter nie sprawdza już warunek2. W (warunek1 || warunek2) analogicznie, gdy pierwszy warunek jest prawdziwy, całość jest prawdziwa bez sprawdzania drugiego. Ta właściwość bywa wykorzystywana w praktyce do pisania zwięzłego kodu, ale na poziomie początkującym wystarczy rozumieć, że istnieje i dlaczego może czasem np. nie dojść do wykonania jakiejś funkcji umieszczonej jako drugi warunek.
Na koniec tej części należy zauważyć, że wyrażenia w JavaScript mogą zawierać wiele operatorów na raz. W takich sytuacjach obowiązuje priorytet operatorów oraz kolejność obliczania. Dla przykładu, w wyrażeniu 1 + 2 * 3 najpierw wykonywane jest mnożenie (2 * 3 = 6), a dopiero potem dodawanie 1 + 6 = 7, ponieważ operator * ma wyższy priorytet niż +. Można i warto używać nawiasów () w celu wymuszenia własnej kolejności lub po prostu dla czytelności. Na przykład zapis (1 + 2) * 3 sprawi, że dodawanie wykona się przed mnożeniem (dając wynik 9). Jeśli nie jesteśmy pewni, który operator wykona się jako pierwszy, najlepiej dodać nawiasy lub rozbić wyrażenie na mniejsze części – poprawi to czytelność kodu i zmniejszy ryzyko błędów.
Podsumowując, operatory i wyrażenia pozwalają nam manipulować danymi i wykonywać obliczenia. Dzięki nim możemy na przykład obliczać formuły matematyczne, porównywać wartości czy łączyć teksty. Rezultaty operacji często wykorzystujemy w kolejnych instrukcjach programu – szczególnie ważne jest użycie wyników porównań i operacji logicznych w instrukcjach warunkowych, które omówimy w następnej części.
