Chcę zostać kotem internetu – wstęp do programowania – JavaScript cz. 2

devkot.pl 1 rok temu

Pierwsza część artykułu, dostępna pod tym linkiem: Chcę zostać kotem internetu – wstęp do programowania – JavaScript cz. 1, skupiała się na podstawach JavaScriptu takich jak jego historia oraz zastosowania. W drugiej części tego artykułu będziesz miał okazje zapoznać się z podstawami programowania w JavaScript. W ramach tego artykuły przedstawię Ci również polecaną, według mnie, ścieżkę nauki. Czyli jak się zabrać za pracę z JavaScript od podstaw i na co zwrócić uwagę, aby uniknąć frustracji.

JavaScript - podstawy

Jak mogłeś przeczytać w poprzednim artykule JavaScript to skryptowy oraz interpretowany język programowania, ale co to w ogóle oznacza? Interpretowany język programowania oznacz, iż nie posiada on swojego kompilatora czyli, iż jest on „na żywo” tłumaczony na kod maszynowy zrozumiały dla urządzenia, które go wykonuje. Kiedy przeglądarka uruchamia kod JavaScript, tak naprawdę najpierw tłumaczy go na język bezpośrednio rozumiany przez komputer, a następnie go wykonuje. Ma to swoje zalety oraz wady, ponieważ dzięki temu można w bardzo łatwy i szybki sposób wprowadzić zmiany w kodzie i wrzucić je na serwer. Wystarczy tylko zmienić plik źródłowy i voila. Właśnie opublikowałeś nowe zmiany. W przypadku języków kompilowanych proces aktualizacji wersji jest bardziej złożony, ale o tym przeczytasz w jednym z kolejnych artykułów. Jeśli zaś chodzi o minusy to utrudnia sprawdzanie poprawności kodu, ponieważ nie posiada kompilatora, więc istnieje ryzyko, iż o błędach w kodzie dowiesz się dopiero na środowisku produkcyjnym.

Zmienne w JavaScript

JavaScript jest dynamicznie typowanym językiem programowania. Oznacza to, iż programista nie musi jawnie deklarować typu zmiennej. Jej typ jest dedukowany w trakcie wykonywania programu. Do deklarowania zmiennych można wykorzystać poniższe słowa kluczowe:

  • var – deklaruje zmienną w aktualnym kontekście wykonania z opcjonalną inicjalizacją
  • let – deklaruje zmienną w zasięgu bloku z opcjonalną inicjalizacją
  • const – deklaruje stałą w zasięgu bloku (nie można zmienić wartości przypisanej do tej zmiennej)
Pewnie zastanawiasz się czym w praktyce różnią się te 3 słowa oraz co to znaczy, iż zmienna jest zadeklarowana w aktualnym kontekście oraz w zasięgu bloku? W dowolnym języku programowania zmienne mają swój zasięg tzw. scope, określa on to gdzie możemy korzystać z konkretnej zmiennej w kodzie, który piszemy.
Zacznijmy od określenia zasięgu dla zmiennych utworzonych dzięki słów let oraz const. Ich zasięg jest najbardziej intuicyjny oraz ogranicza się do bloku kodu, w który zostały utworzone. Ale czym adekwatnie jest blok kodu? Blok kodu jest to fragment zapisany między znakami { oraz }. Na przykład:
function test() { let x = 1; const z = 2; }

Specyficznym typem bloku kodu jest skrypt, który nie zawiera zewnętrznych znaków { oraz }. W takim przypadku zasięg zmiennej jest globalny dla kontekstu wykonania.

Powyższy blok kodu deklaruje funkcje o nazwie test, której jedynym zadaniem jest utworzenie zmiennych typu let oraz const. Ich zasięg jest ograniczony do klamry (}) zamykającej funkcje.

Kontekst wykonania

Pewnie zastanawiasz się czym jest ten cały kontekst wykonania oraz dlaczego zakres zmiennych od niego zależy. Zatem przejdźmy do sedna. Kod JavaScript potrzebuje specjalnego środowiska do działania, w większości przypadków tym środowiskiem jest przeglądarka internetowa. Możemy wyróżnić 2 konteksty wykonywania w JavaScript:

  1. Kontekst globalny – Global Execution Context (GEC)
  2. Kontekst funkcji – Function Execution Context (FEC)

Kontekst globalny

Jest to domyślny kontekst wykonywania dla kodu JavaScript. Przeglądarka tworzy go w momencie gdy wbudowany silnik JavaScript zacznie wykonywanie skryptu. Odpowiada za wykonywanie całego kodu JavaScript, który nie został zapisany w funkcjach. Jest niezależny od plików źródłowych tzn. kod zapisany w dowolnym pliku JavaScript ma dostęp do globalnego kontekstu. Dzięki temu może odwoływać się do zmiennych oraz funkcji, które zostały w nim zadeklarowane. Jest on domyślnym kontekstem dostarczanym przez przeglądarkę internetową.

Kontekst funkcji

Za każdym razem, gdy wywoływana jest funkcja tworzony jest specjalny kontekst wykonania. W związku z tym zmienne utworzone wewnątrz tej funkcji są dostępne tylko dla niej i po zakończeniu jej działania są usuwane z pamięci i nie można uzyskać do nich dostępu z zewnątrz.

Jak tworzony jest kontekst wykonywania ?

Tworzenie kontekstu wykonywania można podzielić na 2 etapy:

  1. Faza kreacji
  2. Faza wykonania
Pierwsza z nich odpowiada za parsowanie (przetwarzanie) oraz interpretację (zamianę kodu JavaScript na kod maszynowy). W ramach tego procesu przeglądarka odpowiada za rezerwację miejsca w pamięci dla zmiennych oraz funkcji zadeklarowanych w ramach kontekstu wykonania. Dodatkowo ten etap odpowiada także za windowanie.
Windowanie jest to proces w ramach, którego deklaracje funkcji są przenoszone na sam początek kodu. Natomiast zmienne, utworzone dzięki słowa kluczowego var, są zapisywane w pamięci oraz jest do nich przypisywana domyśla wartość dla JavaScript, czyli undefined. Przypisanie docelowej wartości zostaje w tym samym miejscu. Dzięki windowaniu możemy korzystać z funkcji, które w kodzie znajduję się poniżej wykonywanej linijki. Zmienne typu let oraz const mimo, iż również są windowane zachowują się inaczej od tych zadeklarowanych słowem var. Mianowicie pomimo, iż również zostały zapisane w pamięci, to nie posiadają przypisanej żadnej wartości oraz nie możemy z nich korzystać w kodzie uruchamianym przed linijką, w której zostaną zainicjalizowane.
Wiem, iż to wszystko może wydawać się skomplikowane, ale spokojnie mam nadzieję, iż przykłady rozwieją wątpliwości

Przykładowy kod JavaScript

Skoro już wiesz, czym różnią się słowa var, let oraz const oraz dowiedziałeś czym jest kontekst wykonania, to nie zostaje nic innego jak sprawdzić jak to działa w praktyce. Poniżej znajduje się przykład, który przedstawia w praktyce zakres zmiennych utworzonych dzięki tych 3 słów kluczowych oraz to jaki wpływ na ich zakres mają konteksty wykonania:

test(); function test() { let y = 2; const z = 1; (function() { var x1 = 3; let y1 = 2; const z1 = 1; console.log(x); // "undefined" console.log(y); // "2" console.log(z); // "1" console.log(x1); // "3" console.log(y1); // "2" console.log(z1); // "1" })(); console.log(x); // "undefined" console.log(y); // "2" console.log(z); // "1" console.log(x1); // error console.log(y1); // error console.log(z1); // error } console.log(x); // "undefined" console.log(y); // error console.log(z); // error var x = 3; console.log(x) // "3"

Jak możesz zauważyć w powyższym przykładzie mamy różne konteksty wykonania, na początku deklaruje gminne dla kontekstu globalnego, następnie wewnątrz funkcji test tworzę 2 konteksty funkcyjne. Jeden dla funkcji nazwanej test() drugi dla funkcji anonimowej. Jak widać największy zasięg ma zmienna var x, która została utworzona pod koniec skryptu. Na powyższym przykładzie zmiennej x możesz zobaczyć jak działa windowanie. Pomimo, iż jej deklaracja znajduje się na końcu skryptu to w kodzie znajdującym się nad jej inicjalizacja (linia 32) możesz się do niej odwoływać. Jednak w przypadku odwołania się do niej jej wartością będzie „undefined”. Reszta zmiennych natomiast ogranicza swój zasięg do bloku, w którym została zdefiniowana.

Pętle

Kolejnym ważnym elementem języka JavaScript są pętle. Jest to wyrażenie, które pozwala wykonać kod zawarty w bloku x razy. To ile razy pętla się wykona zależy od warunków oraz jej typu. JavaScript udostępnia poniższe typy pętli:

  • for
  • while
  • do…while
  • forEach
  • for/in

Pętla for

Jest to jedna z najczęściej stosowanych typów pętli. Jej składnia wygląda następująco:
for([zmienne]; [warunek końca pętli]; [zmiana zmiennych]) { . . // Kod pętli . }

Pętla for składa się z 3 kluczowych elementów:

  • [zmienne] – w tym miejscu należy zdefiniować zmienne, które będą wykorzystywane do sterowania pętlą. Bardzo często w tym miejscu tworzy się tzw. licznik, który liczy ile razy dana pętla się wykonała. Te zmienne wykorzystuje się do sprawdzania w warunku końca pętli. Ta część kodu jest wykonywana przed wejściem w pętle.
  • [warunek końca pętli] – instrukcja warunkowa, która odpowiada za wyjście z pętli. Jest wykonywana przed każdym krokiem pętli. jeżeli jej wartość wynikowa to true oznacza to, iż należy wykonać krok. Natomiast jeżeli będzie to false to znak, iż należy opuścić pętle.
  • [zmiana zmiennych] – jest to miejsce, w którym należy zdefiniować to jak powinny zmieniać się zmienne po każdym kroku pętli.
Przykład:
for (let i = 0; i

Powyższy przykład przedstawia przykładową pętle for, której jedynym zadaniem jest wypisanie informacji na konsoli. Pętla wykona się dziesięć razy i powinna wypisać na konsoli komunikat Krok nr [0-9].

Pętla while

Kolejnym bardzo ważnym rodzajem pętl w JavaScript są pętle while i do..while. Różnią się one od for tym, iż przyjmują jedynie warunek wykonania pętli.
while([warunek]) { . . // Kod pętli . } do { . . // Kod pętli . } while([warunek])

Te 2 pętle są do siebie bardzo podobne, ale różni je 1 bardzo ważna cecha. W przypadku pętli do…while kod pętli zostanie wykonany minimum 1 raz, ponieważ w tym przypadku warunek jest sprawdzany dopiero po wykonaniu kodu pętli i sprawdza czy należy przejść do następnego kroku. Natomiast w przypadku pętli while jest on sprawdzany przez wejściem do pętli i przed każdym następnym krokiem.

Jeśli zainteresował Ciebie temat pętli to polecam sprawdzić ten artykuł, który przedstawia więcej przykładów: Pętle w JavaScript

Instrukcje warunkowe

Pisząc aplikację często zdarza się, iż zależnie od danych, które przetwarzamy chcemy wykonać jedną, bądź drugą akcję. W tym celu można wykorzystać instrukcje warunkowe, które służą właśnie do wykonywania danego fragmentu kodu w przypadku gdy warunki wstępne będą spełnione. Służy do tego słowo najważniejsze if.
if ([warunek]) .. //linia kodu do wykonania if ([warunek]) { . . // kod do wykonania . }

W ten sposób możesz definiować kod, który zostanie wykonany tylko i wyłącznie w przypadku gdy [warunek] zwróci wartość true. Warunkiem może być dowolne wyrażenie, którego wynikiem jest wartość logiczna true/false. Jako warunek można również wywołać funkcje, która zwróci wartość logiczną. Takie wyrażenie może składać się z kilku członów, które mogą być połączone ze sobą dzięki logicznych operatorów AND (&&) oraz LUB (&&).

Operatory logiczne

Logiczne operatory pozwalają na złączenie kilku warunków zgodnie z zasadami algebry Boole’a. Operator AND oznacza, iż wszystkie składniki wyrażenie muszą zwracać true natomiast OR wymaga zwrócenia tylko 1 wartości true. Na poniższym przykładzie możesz zobaczyć jak to wygląda w praktyce:

let x = 1; let y = 2; let z = 3; // x === 1 - true // y === 2 - true // z === 3 - true // true && true && true = true - wszystkie warunki zotsały spełnione if (x === 1 && y === 2 && z === 3) console.log(true); // x === 1 - true // y === 2 - true // z === 3 - false // true && true && false = false (aby AND zwrócił true wszystkie wartości muszą być true) if (x === 1 && y === 2 && z !== 3) console.log("Ten kod nie zostanie wykoany") // x == 1 - true // z === 2 - false // true || false = true if (x === 1 || z === 2) (wystarczy 1 true) console.log(true); // x === 1 - true // (y === 2 || z === 2) - (true || false) - true // true && true = true if (x === 1 && (y === 2 || z === 2)) comsole.log(true)

Powyższy przykład przedstawia różne warunki oraz to jak działają operatory logiczne. jeżeli jeszcze nie jest to dla Ciebie zrozumiałe to spróbuj zdefiniować jakieś swoje własne warunki oraz spróbuj zapoznać się z tym artykułem.

W JavaScript możesz porównywać wartości na kilka sposobów:

  • x > y – x większe niż y
  • x >= y – x większe bądź równe y
  • x < y – x mniejsze niż y
  • x <= y – x mniejsze bądź równe y
  • x == y – porównanie obiektów (konwertuje zmienne na ten sam typ, jeżeli zmienne są różnych typów może zostać zwrócony true, jeżeli uda się zrzutować i będą równe)
  • x === y – porównanie obiektów (bez konwersji, jeżeli zmienne są różnych typów zostanie zwrócony false) –
  • x != y – x różne od y
  • x !== y – x różne od y

If..Else

Oprócz samego definiowania kodu, który powinien być wykonywany warunkowo możesz również zdecydować jaki kod powinien być wykonany jeżeli warunek nie zostanie spełniony. Służy do tego słowo najważniejsze else. Przykład wykorzystania if…else:
let x = 1; if (x === 1) { console.log("Chyba przeszło!"); } else { console.log("Czekaj, coś jest nie tak. Wartość x się zmieniła!"); }

Powyższy przykład przedstawia instrukcję warunkową, która wypiszę tekst Chyba przeszło! w przypadku gdy x jest równy 1. Natomiast, jeżeli zmienisz wartość x to zostanie wyświetlony komunikat Czekaj, coś jest nie tak. Wartość x się zmieniła!.

If…Else…If

Powyższą konstrukcję można jeszcze utrudnić. dzięki słów kluczowych if…else możesz utworzyć również bardziej skomplikowane konstrukcje. W ramach przykładu przyjmijmy, iż mamy do napisania kod, który będzie naliczał zniżki dla użytkowników. W przypadku gdy użytkownik zarejestrował się ponad rok temu to należy mu przyznać zniżkę 60%, jeżeli pół roku temu to 30%.
let userRegisteredMonthsAgo = 2; var discount = 0; if (userRegisteredMonthsAgo >= 12) { discount = 0.6; } else if (userRegisteredMonthsAgo > 6) { discount = 0.3; } else { discount = 0; }

Operator warunkowy

Często spotykaną alternatywą if…else jest operator warunkowy. Służy on zwykle do warunkowego przypisywania wartości do zmiennej. Często można spotkać go pod nazwą operator trenarny. Jego składnia wygląda następująco:
[warunek] ? [wartość gdy true] : [wartość gdy false] let x = money

Funkcje w JavaScript

Jednymi z podstawowych elementów, z których składają się skrypty JavaScript są funkcje. Pozwalają one na napisanie kodu, który może być używany w wielu miejscach w kodzie. Niezależnie od języka programowania, jeżeli piszemy kod, który może być używany w kilku miejscach w kodzie powinniśmy napisać go jako funkcje. Wynika to z jednej z zasad tworzenia oprogramowania, a dokładniej z zasady DRY (Don’t Repeat Yourself). jeżeli zauważysz w kodzie jakiś zduplikowany fragment kodu to jest to dobre miejsce do refaktoryzacji kodu. W takim przypadku ten zduplikowany fragment kodu powinien zostać przeniesiony do nowej funkcji, a w jego miejscu powinno pojawić się wywołanie nowo utworzonej funkcji. Dzięki temu, jeżeli w przyszłości będzie potrzeba zmiany kodu, lub poprawy jakiegoś błędu to wystarczy zmienić go w 1 miejscu.
Funkcje to bardzo potężne i użyteczne narzędzie. Dzięki ich stosowaniu możesz dużo szybciej pisać kod, ponieważ powtarzalną logikę wystarczy napisać tylko raz i używać jej z wielu miejsc. Ale jak tworzyć takie funkcje w JavaScript? Składnie funkcji możesz zobaczyć na poniższym przykładzie:
function ([argument1], [argument2], ...) { . // kod . // kod . // kod [return ] }

Składnia funkcji składa się z:

  • <nazwa-funkcji> (wymagane) – unikalny identyfikator, wykorzystywany do wywoływania.
  • [argument1], [argument2] (opcjonalne) – są to argumenty (zmienne) przekazywane to funkcji. dzięki tych elementów można przekazać dane, na których funkcja będzie operować.
  • [return <wartosc>] (opcjonalne)- funkcje mogą również zwracać wartość. Wykorzystywane jest do tego słowo return.

Polecana ścieżka nauki

jeżeli planujesz dalej rozwijać się jako programista JavaScript to powyższa teoria to tylko początek Twojej drogi! Pozwoli Ci ona pisać pierwsze skrypty, które mogą być uruchamiane np. przez przeglądarki internetowe. Jest to dobry moment, aby poświęcić chwilę na przyswojenie powyższej wiedzy w praktyce, tak abyś czuł, iż rozumiesz o co w tym chodzi oraz, iż jesteś gotowy przejść na kolejny etap swojej nauki. Poniżej znajdziesz polecaną przeze mnie ścieżkę nauki dla programisty JavaScript, tym razem przedstawiam bardziej hasła, które należy zgłębić:

  1. Zmienne
  2. Typy danych
  3. Instrukcje warunkowe
  4. Pętle
  5. Funkcje
  6. Tablice
  7. Obiekty
  8. Modyfikowanie DOM dzięki JavaScript
  9. ES6 – zapoznanie się konceptami przedstawionymi w ES6
  10. forEach, map, filter
  11. Obiektowość wprowadzona od ES6
  12. Moduły (import oraz export)
  13. Frameworki JavaScirpt (Angular/React/Vue/…) – można wybrać 1

Podsumowanie

Uff, dziś było dużo teorii, jeżeli dotarłeś do tego miejsca to wierzę, iż jesteś zmotywowany do zmiany pracy. Teraz czeka na Ciebie sporo pracy, aby zgłębić wszystko w praktyce. Wierzę, iż dasz radę i do zobaczenia w kolejnych artykułach.
Idź do oryginalnego materiału