JavaScript 10.11

Operatory i konwersja typów

Automatycznie JS próbuje wykonać konwersje danych podczas tych operacji

Operator dodawania - służy do sumowania wartości liczbowych lub do łączenia stringów. Jeśli jeden z operandów/argumentów które mamy jest stringiem to ten operator zmienia swoje zachowanie i zamiast operacji matematycznej robi operacje łączenia znaków const suma = 10+5;

Operator odejmowania - jeśli operandy mają wartość liczbową, to te wartości się odejmą const roznica = 10-5;

Operator mnożenie iloczyn = 10*5;

Operator dzielenie iloraz= 10/5;

Operator modulo reszta = 10% 3; czy liczba jest podzielna przez daną liczbę, bardzo użyteczny w sprawdzaniu parzystości liczb, w wykrywaniu i implementowaniu logiki cyklicznej co czwarty raz zrób coś np.

Operator potęgowania potega = 2**3; można użyć funkcji matematycznej ale to jest łatwiejsze

Operatory porównania

Zwracają boolean - true/false.

porównania luźne - porównania, które automatycznie konwertują typy danych, a w związku z tym ułatwiają życie, ale mogą prowadzić do błędów

const liczba=5; const tekst="5";

const luznaRownos = liczba == tekst;

const scislaRownosc = liczba === tekst; nie tylko wartości, ale konwersja - jesli wartosci sie nie zgadzaja ich typ, to sie nie zgadzaja, wiec

Nierównosci

const luznieNierownie = liczba != tekst;

const scielseNierowne = liczba!== tekst;

Operatory relacyjne

> wieksze const wieksze = 10>5;

< mniejsze con

>= wiekszeLubRowne

Konwersja jawna/niejawna

Implicit conversion javascript sam konwertuje

Explicit conversion my to robimy

ParseInt liczby całkowite

ParseFloat liczby zmiennoprzecinkowe

Number - przekształca na wartość liczbową (Number.isNan() test czy dana konwersja jest możliwa

String() można skonwertować 123 na string

Boolean() prawda/fałsz 0/1

Falsy traktowane jako fałsz: false, 0,-0, 0n (bigInt ma osobne bo to inny typ danych), " ", null, undefined, NaN

Truthy traktowane jako true: true, 1, -1, "0" "false" " " "tekst, bez jawnego porównania możemy sprawdzić czy użytkownik coś nam wpisał, jest to dośc powszechna praktyka

const imie =""; const maImie = Boolean(imie);

Pusty string daje false

Type Coercion niektóre rzeczy są nieintuicyjne

Badanie/Walidacja inputu od uzytkownika:

inputWartosc =25; jeśli bnedzie ="25aaa" to tez skonwertuje ale jeśli jest na poczatku aaa25 to wtedy nie skonwertuje

const liczba = number(inputWartosc);

czypoprawna =!isNan(liczba);

Jeśli mamy formularz, dobrym pomysłem na input od uztykownika jest użycie funkcji trim (usuwa zbede spacje z poczatku i konca)

STOSOWAĆ OPERATORY SCISLE, porównywać nie tylko wartości ale i typy używać JAWNĄ KONWERSJE TYPÓW

Operatory logiczne

Operator AND (&&) zwraca true jeśli oba operandy są truthy, uzywamy kiedy chcemy sprawdzić czy wszystkie warunki sa spełnione np. czy użytkownik jest zalogowany i czy ma uprawnienia do jakiejś operacji

Operator OR (||) zwraca true kiedy chociaż jeden z operandów jest truthy, używamy jeśli chcemy sprawdzic czy jaikolwiek warunek z anszej listy jest spełniony, czesto uzywanmy do ustawiania wartosci domyslnych

Operator NOT (!) operator negujacy wartosc, zamienia truthy na falsy, czesto używany czy coś nie jest prawda albo konwersji wartości na boolean, dwa zaprzeczenia podwójna negacja zwroci true przy !!1;

Operatory logiczne nie zawsze zwracają boolean, mogą zwracać jeden z operandow, jeśli stworzymy taka logikę (nowoczesny sposób SHORT CIRCUIT).

Możemy łączyć operatory

const wiek =25; const maKonto = true; const mozeKupic = wiek >= 18&& maKonto;

Łączenie AND i OR działają logiki matematyki


SHORT CIRCUIT EVALUATION używany by skrócić zapis i wykonać test a po tescie odrazu pokazywać wartość, AND i Or

const wynik1 = false && console.log ("to się nie wykona"); NIE wykona sie jak oba elementy nie sa prawdziwe true

const wynik2= true && "to sie zwróci";

w jednej linijce przypisujemy wartość domyślna i wykonujemy sprawdzenie. Gdzie używać np. obiekty

const miasto=uzytkownik&& uzytkownik.adres && uzytkownik.adres.miasto

Sprawdzamy czy istnieje obiekt, czy w obiekcie istnieje obiekt podrzędny i czy obiekt podrzędny nie jest pusty

Działa dla OR

W ten sposób jesteśmy w stanie walidować rożnego rodzaju wartości, czy to walidować funkcje, czy to zwraca wartości które są prawidłowe.

Nullish coalescing ?? rozwiązuje problem z używaniem operatora OR do ustawiania wartości domyślnych

Jeśli w OR pierwsza wartość jest false to będzie falsy wiec jak ustawimy domyślna wartość na 0 to przy użyciu operatora OR to nie weźmie tego pod uwagę, a w przypadku kiedy tworzymy domyślne konfiguracje to może zdarzyć się tak, że domyślna wartość dla nas to 0. Operator ten nie może być użyty z AND i OR bez użycia nawiasów - zabezpiecza to przed niejednoznacznością, a nawias mówi która operacja ma być wykonana jako pierwsza.

Optional Chaining ?. upraszcza prace z zagnieżdżonymi obiektami, np. z właściwościami które w tych obiektach mogą nie istnieć

Jeśli wartości która sprawdza nie ma to zwraca undefined

Optional Chaining działa też z funkcjami, może sprawdzić czy metoda stworzona w funkcji istnieje. A jeśli nie istnieje to jest undefined a nie brak bledu wiec nam nie wywali kodu - miękkie sprawdzenie graceful error handling

Działa tez z tablicami np. czy dany index istnieje, a jeśli nie istnieje daje undefined

Optional Chaining można ustawić wartości domyślne, jeśli jakaś wartość domyślna nie jest ustawiona to można wtedy jej to przypisać


Operator Precendence pierwszeństwo operatorów, który operator ma się pierwszy wykonać

  1. operatory arytmetyczne wyższe niż porównania
  2. porównania wyższe niz op logiczne
  3. nawiasy najwyższe pierwszeństwo

NOT, AND, OR - w takiej kolejności wykonują się operatory logiczne


Inne operatory:

Przypisz jeśli zmienna turthy &&=

Przypisz jeśli zmienna falsy ||=

Przypisz jeśli zmienna null/undefined ??=

Przydatne przy warunkowym modyfikowaniu obiektów, kod jest b zwięzły, ale nie jest to konieczne.

Podsumowanie:

Jeżeli używamy notacji short circuit i jeśli poprawna wartością jest 0 lub false lub pusty string to zamiast OR || używamy nullish coalesing ??

Jeżeli potrzebujemy dostać się do wartości obiektu i chcemy to zrobić w sposób bezpieczny, jeśli tej wartości nie ma, klucz nie istnieje itd. używamy optional chaning ?.

operator precendence


Instrukcje warunkowe

IF

IF jeżeli, sprawdza czy w wyrażeniu które jest podane w nawiasie jest prawdziwe, jeśli tak wykonuje blok kodu, oceniamy czy truthy czy falsy, nie musi byc boolean.

if (wiek >= 18) { console.log("użytkownik jest pełnoletni");}

Instrukcje if mogą być zagnieżdżone

if (punkty >=50) { console.log ('test zaliczony");

if (punkty >=80) { console.log("doskonały wynik")};

mogą być też złożone z więcej niż 1 warunku

if (temperatura > 20 && jestSlonecznie) { console.log("świetna pogoda na spacer");}

Zmienne mogą być w instrukcji ale mogą być zadeklarowane globalnie

ELSE rozszerza możliwości IF pozwala na określenie kodu w przeciwnym wypadku jeżeli nie. Pozwala na podzielenie logiki, jeśli cos nie, to wtedy to

Musi być umieszczony bezpośrednio po bloku IF i nie może istnieć samodzielnie

Podstawowy IF-ELSE

const godzina =14;

if(godzina <12) { console.log("dzień dobry");} else { console.log("dobry wieczór");} pokaże dobry wieczor bo warunek nie jest spełniony

ELSE-IF zostanie wykonana pierwszy spełniony warunek, ignoruje pozostałe, umieszczamy między IF a ELSE. Kolejność warunków ma znaczenie, jeśli warunki się pokrywają to te b. specyficzne powinny być sprawdzanie jako pierwsze

if

else if

else if

else if

else

W instrukcjach warunkowych możemy łączyć operatory logiczne i arytmetyczne.

Instrukcja przestanie działać w momencie kiedy pierwszy z warunków zostanie spełniony.

Teoretycznie jest możliwe nie używanie nawiasów klamrowych, jeśli mamy tylko 1 instrukcje, ale lepiej używać nawiasów klamrowych zawsze w każdym przypadku, nawet dla jednej linii kodu. Jeżeli mamy złożone warunki, to zwracać uwagę na nazwy zmiennych, by nazwy zmiennych były opisowe nosiły informacje, bo inaczej ciężko się intepretuje złożone warunki jeżeli one nie są opisowe.

Unikać zbyt głębokiego zagnieżdżania, tak samo jak w tabelach listach itd. Jeśli kod ma więcej niż 3 poziomy zagnieżdżenia, staje się ciężki do śledzenia.

Rozważyć czy negative conditionals zaprzeczenia są konieczne, zwłaszcza gdy warunki są skomplikowane, może nie są potrzebne.


Switch

alternatywa dla długich łancuchów if-else. Szczególnie przydatna jeżeli porównujemy sprawdzamy wartość która ma potencjalnie wiele wartości. Każdy case reprezentuje jedną wartość. Jeśli case zostanie znaleziony kod bloku zostanie wykonany. Switch został zaprojektowany tak, ze używa ścisłego porównania oznacza to ze typ danych musi się zgadzać, jeśli badamy liczby string nie działa itp. Na końcu każdego bloku umieszczamy break; to daje informacje do przeglądarki do JS, ze jak ten kod się wykona to cały switch ma się zakończyć.

default - opcjonalny, działa dokładnie tak samo jak else w if-else, wykonuje się wtedy jeśli żaden z case nie pasuje

Switch może występować z wyrażeniami np. &&

Instrukcją warunkową if sprawdzamy obie liczby, natomiast instrukcja switch wybieramy działanie które na tych liczbach się wykona

// Pobranie danych od użytkownika
let liczba1 = prompt("Podaj pierwszą liczbę:");
let liczba2 = prompt("Podaj drugą liczbę:");
let operacja = prompt("Wybierz operację: +, -, *");

// Konwersja na liczby
liczba1 = parseFloat(liczba1);
liczba2 = parseFloat(liczba2);

// Sprawdzenie, czy to faktycznie liczby
if (isNaN(liczba1) || isNaN(liczba2)) {
  alert("Podano nieprawidłową liczbę!");
} else {

    // Wybór operacji
  let wynik;

  switch (operacja) {
    case "+":
      wynik = liczba1 + liczba2;
      break;
    case "-":
      wynik = liczba1 - liczba2;
      break;
    case "*":
      wynik = liczba1 * liczba2;
      break;
    default:
      alert("Nieznana operacja!");
      wynik = null;
  }

  // Jeśli wszystko OK – pokaż wynik
  if (wynik !== null) {
    console.log(`Wynik: ${liczba1} ${operacja} ${liczba2} = ${wynik}`);
    alert(`Wynik: ${liczba1} ${operacja} ${liczba2} = ${wynik}`);
  }
}

Fall-through grupowanie wartości np. podajemy w case dzień tygodnia i od pon do pt podaje dzień roboczy robimy break dla przypadku sobot niedziela wypada typdnia weekend, potem znow break. Fall-thorugh to przepuszczanie do kolejnych caseów, jeśli brakuje instrukcji break to JS przechodzi do kolejnych caseów, on nie sprawdza case tylko wykonuje kod, on nie sprawdza tych warunków tylko dla tych wszystkich warunków to X jest spełniony. Jak jest break to kończy kod, jak nie ma break to będzie wykonywać wszystkie warunki/opcje. Najlepiej wpisać komentarz ze to jest celowe fall-through.


TERNARY krótsza notacja zapisu if-else, można przypisać do zmiennej wartości

Ternary można używać w wyrażeniu

Można używać jako wywoływanie funkcji

NIE ZAGDNIEŻDZAĆ TERNARY


Pętle

Po co stosować pętle - jak mamy wiele operacji, możemy zautomatyzować kod, nie musimy go przepisywać x razy, ale możemy go wsadzić w pętle

Pętla w JS składa się z 3 części

Warunek początkowy - ustawienie kiedy pętla startuje

Warunek który ma być spełniony i jak długo ten warunek jeśli spełniony ma działać

Implementacja czyli ile razy pętla ma działać

Wszystkie instrukcje które umieścimy w pętli

FOR

for (let i =1; i<=5; i++) {console.log(i);} wykona się bo let to zmienna blokowa, i jest zdefiniowana w ciele pętli i jest specyficzna dla tego kawałku bloku. Jeśli byśmy używali var to by sie nadpisywały te zmienne

Dla pierwszej pętli używamy i - iterator, dla kolejnych pętli używamy j, k itd.

Dla wygody dla siebie można zadeklarować zamiast i swoja zmienna która będziemy rozumieć

Jako, ze tablice adresowane są od 0, konwencje programistyczne zachęcają by pętle również zaczynać od 0

i++ do przodu, jeśli chcemy co dwa co trzy co pięć i=i+7 i+=7

i- - wstecz

Iteracja po tablicy

Działają w FOR wszystkie operatory, operacje.

sumowanie wartości += do bieżącej wartości dodaje i

Można w for wyszukiwać w tablicy

Możemy budować w pętli elementy HTML - np. listy punktowane, mamy do wyświetlenia kawałek tablicy, obiektu itd i wyświetlić chcemy kawałek tego np. kartę użytkownika

WHILE

działa jak for, wykonuje kod dopóki warunek jest prawdziwy. For ma wszystkie części kontrolne w jednym miejscu, while wymaga ręczne zarządzanie zmiennymi sterującymi, wymaga od nas więcej uwagi

let licznik=5; zadeklarowana zmienna przed pętlą

while (licznik>0){

console.log(licznik);

licznik - -

}

While z flagą kontrolną

const liczby - tablica

let indeks ustawiamy na 0 by zacząć od 1 pozycji

let znaleziono = false na poczatek ustawiamy

ustawiamy warunek, tak długo warunek ma się kręcić jak indeks liczby ma być mniejszy od długości tablicy indeks < liczby.lenght && !znaleziono i kręcimy tak długo pętla jak długo indeks jest w zakresie, jesli znajdziemy warunek to zmieniamy zmienna znaleziono=true

Jak źle wybierzemy warunki inicjalizacji to pętla w ogóle się nie wykona np. let x=10, while x<5 nie działa

DO...WHILE

Chociaż raz, ale zawsze się wykona. Pobieranie hasła użytkownika, pobieranie wartości do kalkulatora. Zrób to i to jeśli (tu można wsadzić ify), while na końcu. Pobieramy dane a potem sprawdzamy warunki dodatkowe

while wykona się tylko wtedy kiedy warunek jest spełniony, jak warunek nie dobry while jest pomijany

do while najpierw wykona kod a potem sprawdzi warunek, wiec chociaż raz pętla się wykona

WHILE z break jak licznik ma np. 3 to pętla się zakończy, jak nie ma jasnego warunku kiedy pętla ma się zakończyć, wiec lepiej np skontrolować ze się wykona x razy - gry w JS spora część while (true) rób, jeśli, przerwij, koniec

break- wczesne zakończenie pętli

continue - nie zatrzymuj się na tej iteracji, idź dalej, np. pomiń liczby parzyste

Zagnieżdżone pętle - breaki działają na konkretne pętle