w Praktyce
9 godz. 47 min · JavaScript · Full-stack i Programowanie
Piotr PalarzWeb DeveloperW pierwszym rozdziale tego kursu poznasz bardzo dokładnie koncepcje programowania zorientowanego obiektowo. W jednej z lekcji, omówimy wszystkie z nich na przykładzie pseudo-kodu, niezwiązanego bezpośrednio z językiem JavaScript. Dzięki temu zrozumiesz, jak realizowane jest programowanie obiektowe w wielu popularnych językach programowania. Dowiesz się czym jest klasa, obiekt, instancja, właściwości, metody, a także zrozumiesz takie pojęcia jak dziedziczenie, polimorfizm, abstrakcja czy enkapsulacja. Następnie przejdziemy już do języka JavaScript i do zrozumienia tego, w jaki sposób powyższe koncepcje są w nim zaimplementowane. Język ten nie jest bowiem w 100% klasycznie obiektowy, jak np. język PHP. Co jednak bardzo istotne, JavaScript implementuje tzw. dziedziczenie prototypowe, którego bardzo dogłębne zrozumienie, gwarantuje zrozumienie całego języka JavaScript. Dowiesz się zatem czym są konstruktory i jak je tworzyć, a także jak korzystać z prototypu funkcji. Dzięki temu będziemy mogli wykorzystać obiektowość do własnych celów, co później w praktycznych przykładach uczynimy.Na przestrzeni kilku lekcji zobaczysz krok po kroku, jak w języku JavaScript zaimplementować dziedziczenie wielokrotne. Taka wiedza absolutnie otwiera oczy na zależności rządzące obiektami w tym języku. Dowiesz się również jak rozszerzać wbudowane konstrukcje języka JavaScript czy Obiektowego Modelu Dokumentu, a także kiedy powinniśmy to robić. Omówimy problemy, jakie mogą się pojawiać przy korzystaniu ze słowa kluczowego this, a także sposoby ich rozwiązania. Poznasz 3 bardzo ważne metody funkcji: call, apply i bind.JavaScript ma wiele specyficznych cech, a jedną z nich są tzw. domknięcia. W jednym z rozdziałów zobaczysz, do czego one służą i kiedy powinniśmy z nich korzystać. Dopełnimy tym również wiedzę związaną z programowaniem obiektowym i tzw. prywatnością.Rozdział o obiektowości został celowo umieszczony na samym początku kursu, gdyż zrozumienie tych koncepcji pozwala patrzeć zupełnie inaczej na wszystkie pozostałe. Po tym rozdziale przejdziemy do omówienia bardzo popularnego, lekkiego formatu wymiany danych JSON. Dowiesz się jak wygląda składnia tego formatu, a także jak współpracuje on z językiem JavaScript.Następnie przejdziemy do bardzo ekscytującego tematu, jakim jest technologia AJAX. Dzięki niej możemy wysyłać zapytania do serwera i pobierać dane, bez przeładowywania witryny. Do zrozumienia AJAXa niezbędne jest jednak rozumienie działania protokołu HTTP, na którym opiera się sieć www. Z tego powodu, jedna z lekcji została w 100% poświęcona HTTP i dowiesz się z niej jak wysyłane są żądania i odpowiedzi, a także tzw. nagłówki, które będą dla nas niezwykle istotne. Chwilę później omówimy również bardzo ważne mechanizmy: Same- origin policy i CORS, które blokują możliwość wysyłania żądań AJAX do pewnych serwerów. Kiedy już będziesz rozumiał te niezwykle istotne koncepcje, przejdziemy do napisania pierwszego kodu, wysyłającego asynchroniczne żądanie do serwera. Następnie dowiesz się jak wysyłać, a także odbierać dane z serwera, umieszczać je na stronie oraz śledzić postęp zarówno wysyłania, jak i pobierania danych.W tym rozdziale na przestrzeni kilku lekcji napiszemy swoją własną bibliotekę AJAX, która pozwoli w niezwykle łatwy sposób wysyłać i odbierać dane. Skorzystamy w niej już w kolejnej lekcji, gdzie zobaczysz, jak wysłać wiadomość e-mail z użyciem AJAX i PHP po stronie serwera. Gotowy skrypt, będziesz mógł umieścić na własnej stronie internetowej. Na zakończenie tego rozdziału omówimy również dokładnie niezwykle sprytną technikę o nazwie JSONP, które pozwala wysyłać tzw. żądania “cross-origin”. Przekonasz się dlaczego taka technika powstała i jak współpraca klienta i serwera potrafi obejść zabezpieczenia przeglądarek.Kolejnym tematem omówionym w kursie będą Cookies, czyli tzw. ciasteczka. Dowiesz się czym są, w jakim celu istnieją, a także jak są ustawianie przez serwer. Co ciekawe, również z poziomu języka JavaScript będziemy mieli do nich dostęp, a zatem zobaczysz jak je ustawiać i odczytywać. Na tym etapie przyda nam się wiedza zdobyta w lekcji o protokole HTTP.W kursie znajdziesz również rozdział poświęcony w 100% wyrażeniom regularnym. To mechanizm języka, który pozwala dopasowywać tekst do definiowanych przez nas wzorców. Wyrażenia regularne potrafią być bardzo zaawansowane i odstraszać, dlatego rozłożymy je na czynniki pierwsze, byś dokładnie je zrozumiał. Na przestrzeni wielu lekcji dowiesz się jakie są specjalne symbole wykorzystywane przy wyrażeniach regularnych, czym są kwantyfikatory, kotwice czy np. grupowanie. Następnie przejdziemy do wykorzystania wyrażeń regularnych w języku JavaScript. Poznasz zarówno metody obiektu RegExp jak i te dostępne na obiekcie String. Dzięki nim będziemy mogli wyszukiwać np. adresów e- mail w podanym tekście, usuwać je lub zamieniać na coś innego. Jako praktyczny projekt, stworzymy “Antybluzgacz”. Wykorzystamy do tego celu programowanie obiektowe, a sama aplikacja będzie pozwalała filtrować wpisywany przez użytkownika tekst wiadomości i wyłapywać w nim niecenzuralne słowa. Wszystkie z nich zamienimy na przypadkową reprezentację znaków, np. $#!@%^. Ten projekt pokaże Ci nie tylko jak korzystać z wyrażeń regularnych, ale także jak profesjonalnie pracować z kodem JavaScript.W przedostatnim rozdziale tego kursu znajdziesz lekcje związane z dobrymi praktykami pracy. Omówimy tzw. “strict mode” języka JavaScript, zagadnienia związane z minifikacją i konkatenacją skryptów, sprawdzaniem poprawności pisanego kodu oraz delegacją zdarzeń DOM.Na końcu kursu znajdziesz 10 krótkich lekcji z serii Tips & Tricks, które przybliżą Ci wiele ciekawych konstrukcji języka JavaScript, a także technik na rozwiązanie różnych problemów. Zobaczysz np. jak wczytać obrazy w tle czy jak wyświetlić na pasku tytułowym witryny migające powiadomienie.Podsumowując, kurs ten jest dopełnieniem wiedzy z zakresu języka JavaScript i Obiektowego Modelu Dokumentu z kursu “JavaScript od Podstaw”. Poprzedni kurs nie jest wymagany, lecz jego przerobienie z pewnością pozwoli dużo lepiej przyswoić wiedzę z tego kursu, gdyż były one przygotowywane równocześnie. Oba te materiały, pozwolą od zera, wskoczyć na naprawdę wysoki poziom rozumienia języka, a także dobrych praktyk pisania kodu.
Do tego kursu mogą jednak przystąpić wszystkie osoby, które znają już podstawy języka HTML, CSS i JavaScript i chcą poszerzyć swoją wiedzę, a także spojrzeć zupełnie inaczej na ten język.
W tej lekcji chciałbym omówić podstawowe pojęcia związane z programowaniem zorientowanym obiektowo.
Często mówimy programowanie obiektowe,
ale poprawna terminologia jest to programowanie zorientowane obiektowo i to, co mówię w tej lekcji, nie
jest ściśle związane z samym językiem JavaScript.
Będą to ogólnie pojęcia związane właśnie z OOP,
czyli Object Oriented Programming.
Chcę, abyś dobrze poznał wszystkie tzw. paradygmaty programowania zorientowanego obiektowo i później, kiedy
przejdziemy już do przykładów w języku JavaScript,
to pokażę ci, które z nich w języku JavaScript jak wyglądają, dlatego że język JavaScript nie jest w stu
procentach językiem zorientowanym obiektowo, tak jak np. język PHP czy język C++, ale bardzo wiele
z tych koncepcji, które w tej lekcji omówię, mogą być bez problemu zaaplikowane do języka JavaScript. Jeżeli
dobrze zrozumiesz pojęcia, które są w tej lekcji, to również będzie to dla ciebie przydatne, kiedy będziesz
chciał się uczyć programowania zorientowanego obiektowo w różnych innych językach programowania.
Przejdźmy zatem do poznania poszczególnych zagadnień związanych właśnie z Object Oriented Programming.
Jest ich dosyć dużo. Jeżeli chodzi o pojęcia, to te z nich będę chciał omówić właśnie w tej lekcji.
Zaczniemy od klasy i tutaj jest taka uwaga, którą widzisz na dole ekranu.
Powyższy przykład to będzie pseudokod, czyli kod, który tutaj zobaczysz, wygląda jak kod w którymś z języków
programowania. Natomiast nie jest to kod, ani w JavaScript, ani konkretnie w PHP czy w języku Java.
Jest to pseudokod, więc w stu procentach nie jesteś w stanie go wkleić w jakimś konkretnym języku, natomiast
w tym przypadku nie ma to znaczenia.
Więc zacznijmy od tego, czym jest klasa. Klasa jest to taki schemat obiektów, które będą na jej podstawie
tworzone.
No i wyobraźmy sobie klasę, którą nazwiemy Figura.
Możemy w niej mieć właściwości, takie jak ilość boków czy długości tych boków.
Możemy mieć również metody, czyli funkcje, takie jak oblicz obwód czy oblicz pole.
Czyli jest to taki schemat i na podstawie tej klasy będziemy później tworzyć już poszczególne obiekty.
No właśnie, a więc obiekt jest, inaczej mówiąc, instancją klasy i obiekt jest utworzony na podstawie schematu
tej klasy i posiada własne dane.
Właśnie o to w tym chodzi, że pokazałem ci, iż w przypadku klasy mieliśmy np. długości boków, to jest taka
właściwość, to każdy obiekt może mieć własne dane tego typu.
Może to wyglądać w ten sposób, czyli utworzenie dwóch nowych obiektów figura1, figura2 z tej klasy, którą
przed momentem pokazałem. Zobaczmy kolejne pojęcie.
Są to właściwości, czyli properties.
O nich już przed momentem wspomniałem, a więc jeżeli będziemy mieli jakąś klasę, to w niej możemy zapisać takie zmienne,
które przechowują pewne dane i w tym przypadku właściwości to będzie np. ilość boków czy długość boków.
I one będą unikalne dla każdego ze stworzonych obiektów na podstawie tej klasy.
Z kolei metody to będą funkcje, które są dostępne w każdym nowo utworzonym obiekcie i te funkcje mają
dostęp do właściwości, dzięki czemu mogą na nich operować. Czyli w przypadku klasy Figura będziemy mieli
metody, takie jak oblicz pole czy obliczy obwód.
I one właśnie będą miały dostęp do danych przechowywanych w obiekcie, takich jak ilość boków czy długości
boków.
I na tej podstawie będą zwracać odpowiednie dane. W programowaniu zorientowanym obiektowo spotkasz
się również z taką frazą jak konstruktor.
Co to jest konstruktor?
Otóż konstruktor to jest nic innego, jak taka specjalna metoda obiektu, która jest wywoływana zaraz na
początku, kiedy ten obiekt jest z klasy tworzony, czyli kiedy nowa instancja jest tworzona, to konstruktor,
czyli taka specjalna metoda czy funkcja jest wykonywana.
I może to wyglądać następująco. Tak jak tutaj widzisz, nazwałem ten konstruktor
_ _construct.
Tak to wygląda np. w języku PHP. Natomiast może to w innych językach wyglądać zupełnie inaczej.
I teraz kiedy będziemy chcieli sobie utworzyć nowe obiekty na podstawie klasy Figura, to będziemy mogli
przekazać do niego pewne parametry.
Jak widzisz, przekazujemy tutaj czwórkę, a jako drugi w tym przypadku argument przekazujemy tablicę i
właśnie te dane zostaną przekazane do funkcji construct, która zostanie wykonana i następnie zostanie
nam zwrócony już obiekt, który w tym przypadku zapiszemy sobie w zmiennej figura1. Popularnym paradygmatem programowania
jest również dziedziczenie.
Inaczej mówiąc z języka angielskiego inheritance i polega to na tym, że pewne klasy mogą współdzielić funkcjonalności
dostępne na innych klasach po to, abyśmy nie musieli zbyt wiele kodu powielać.
No i teraz zerknijmy sobie znowu na klasę Figura, którą mieliśmy wcześniej.
Jest to taka ogólna klasa, gdzie definiujemy np. ilość boków czy długości poszczególnych boków, a także
metodę oblicz obwód czy oblicz pole.
Natomiast teraz chciałbym utworzyć bardziej wyspecjalizowaną klasę, z której będziemy tworzyć obiekty
i chciałbym sobie ją nazwać Kwadrat, więc moglibyśmy napisać class Kwadrat extends Figura.
Tak to wygląda w niektórych językach programowania.
Jak wspominałem, to jest pseudokod, więc nie do końca musi to działać.
Ale tak to może wyglądać.
I klasa Kwadrat może w tym przypadku, jak widzisz, zdefiniować sobie własną metodę obliczPole, która
będzie działać trochę inaczej, ale ona mimo wszystko będzie dziedziczyć z klasy Figura różne metody, które
tam wcześniej były.
Na przykład taką metodę jak obliczObwod czy właściwość iloscBokow oraz długosciBokow.
Jak widzisz, tutaj na dole możemy utworzyć zmienną Figura1 i następnie obiekt z klasy Kwadrat, przekazując
mu odpowiednie dane, a więc Kwadrat dziedziczy po Figurze i dlatego w klasie Kwadrat nie musieliśmy znowu
przepisywać tego wszystkiego, co znajdowało się już w klasie Figura.
Kolejne bardzo ważne terminy, to jest enkapsulacja, czyli
inaczej mówimy też na to hermetyzacja - z języka angielskiego jest to encapsulation. I to polega na tym, że możemy
ukrywać pewne dane czy pewne metody przed światem zewnętrznym.
Jak to dokładnie wygląda?
Otóż wyobraź sobie, że mamy klasę Figura i ona ma wewnątrz takie właściwości, jak iloscBokow czy
dlugosciBoków, które możemy ustawiać.
Natomiast jeżeli utworzymy sobie nowy obiekt, to tak jak w tym przypadku Figura, to nie chcemy, abyśmy
mogli się odwołać do figura1.iloscBlokow,
tak by to mogło wyglądać w języku JavaScript.
Czyli nie chcemy się móc odwołać bezpośrednio do ilości boków czy do długości boków, ale chcielibyśmy
mieć możliwość odwoływania się do tego przez odpowiednie metody. Czyli np. chcemy na takim obiekcie utworzonym,
który jest pod zmienną figura1, odwołać się do obliczObwod.
Jeżeli zadeklarujemy sobie obliczObwod jako metodę publiczną, to będziemy mogli się do niej odwołać.
Natomiast do iloscBokow nie możemy się odwołać, jeżeli zadeklarujemy to jako zmienna czy składowa właściwość
prywatna.
Mam nadzieję, że na tym etapie to rozumiesz.
Chodzi o to, że chcemy, aby taki obiekt przechowywał pewne dane, ale aby nie można się było do nich po
obiekcie bezpośrednio odwołać.
Wtedy te dane są właśnie ukryte, czyli są hermetyczne.
Natomiast mamy pewne metody, które są dla nas dostępne. Chcemy sobie obliczyć obwód takiej figury, więc
wywołujemy metodę obliczyObwod
i ta właśnie metoda ma dostęp do właściwości iloscBokow, dzięki czemu może nam zwrócić poprawny wynik.
Kolejnym terminem jest abstrakcja i abstrakcja nie wiąże się do końca z jakąś techniczną stroną, czyli
nie jest to coś, co specjalnie zapisujemy w kodzie,
kiedy piszemy programy zorientowane obiektowo. Natomiast abstrakcja jest to bardziej taka forma tworzenia
aplikacji w taki sposób.
Jest to koncepcja, aby one udostępniały nam tylko takie metody, które są nam potrzebne i aby one były ogólne.
A więc przed chwilą pokazałem ci enkapsulację, aby pewne metody czy właściwości były ukryte i aby obiekt
udostępniał nam tylko te metody, które dla nas jako programistów korzystających z takich obiektów, które
ktoś np. napisał, są potrzebne.
Więc abstrakcja łączy się z enkapsulacją i dzięki abstrakcji właśnie, czyli dzięki abstrakcyjnemu myśleniu, możemy
tworzyć takie obiekty, które będą mieć specjalne metody, z których ktoś będzie mógł korzystać, ale będą
mieć także wiele innych ukrytych metod, które będą wykorzystywane przez metody publiczne za naszymi plecami.
O abstrakcji możesz pomyśleć w ten sposób, że np. w samochodzie mamy możliwość wciśnięcia pedału gazu
i wtedy samochód przyspiesza - i wyobraź sobie, że właśnie jesteśmy programistami i korzystamy sobie z takiej biblioteki
pod tytułem samochód i mamy taką metodę przyspiesz czy metodę wciśnij gaz, wtedy przyspieszamy. Natomiast
bardzo wiele różnych rzeczy dzieje się w samochodzie wtedy, kiedy przyspieszamy,
ale my nie musimy o tym wiedzieć, dlatego że nas właśnie interesuje tylko możliwość przyspieszania albo kiedy
wciśniemy hamulec, możliwość zwalniania. I tutaj chcę ci pokazać jeszcze jeden abstrakcyjny przykład.
Bardziej przyziemny, czyli na przykładzie języka JavaScript. Na pewno wielokrotnie na stronach internetowych
widziałeś slidery.
I tutaj mam przykład takiego slidera.
Jest to bxSlider.
No i teraz widzisz, że możemy kliknąć strzałkę w prawo. Zmienia się slide, ale te kropki, które mamy pod
spodem sygnalizujące, na którym slajdzie jesteśmy,
również się zmieniają.
I wyobraźmy sobie, że taka aplikacja, która dana została napisana, udostępnia właśnie metodę
slider.nextSlide.
Tutaj właśnie skorzystaliśmy z tej koncepcji abstrakcji, czyli udostępniliśmy metodę nextSlide, która pozwoli
nam przewinąć do kolejnego slajdu, a że pod spodem przy okazji zmieniane są też te kropki i dzieje się
jeszcze kilka innych rzeczy, to jest to właśnie ta abstrakcja.
Nie musimy o tym myśleć.
To dzieje się automatycznie.
Kolejny bardzo ważny termin jest to polimorfizm.
I tutaj jest to taki mechanizm, który pozwala nam na tworzenie jednolitych klas pomimo tego, że one mogą
się różnić w implementacjach niektórych metod.
i wróćmy sobie tutaj do klasy Figura, o której już mówiłem.
Jest to taka ogólna klasa.
Natomiast gdybyśmy sobie chcieli stworzyć klasę np. Trójkąt, ona będzie rozszerzać,
czyli będziemy tutaj mieli dziedziczenie, o którym już ci mówiłem,
klasy Figura, to wyobraź sobie, że obliczanie pola w przypadku trójkątu to jest zupełnie inny wzór niż
w przypadku kwadratu np. który mogliśmy zaimplementować w klasie Figura.
I teraz co to oznacza?
Otóż nasza klasa Trójkąt będzie dziedziczyć wszystko po klasie Figura, czyli będzie działać tak samo,
ale kiedy odwołamy się do niej i będziemy chcieli obliczyć pole, to tutaj będziemy mieli poprawny wynik w
przypadku Trójkąta. Czyli definiując klasę Trójkąt,
możemy powiedzieć: dziedzicz wszystko z klasy Figura, ale chciałbym inaczej zaimplementować metodę sobie
obliczPole,
chociaż ona nazywa się tak samo.
Dzięki temu będziemy mogli sobie utworzyć nową figurę z klasy Trójkąt i
kiedy odwołamy się do obliczenia pola,
to właśnie ta metoda, którą tutaj zdefiniowaliśmy, zostanie dla nas wywołana
i możemy to zrobić w ten oto sposób.
Jak widzisz, jest to taki mechanizm, który właśnie umożliwia tworzenie jednolitych klas, bo jeżeli taką
bibliotekę, w której mamy właśnie klasy odnośnie figur komuś udostępnimy, to możemy napisać w dokumentacji,
że każda figura ma taką metodę, jak obliczPole.
Na tym właśnie polega polimorfizm, że my będziemy wiedzieli, iż każda figura ma metodę obliczPole, która
zwraca nam właśnie wartość obliczonego pola, ale nie wiemy, jak to zostało zaimplementowane -
czy to dziedziczy rzeczywiście z Figury, czy Trójkąt ma zaimplementowaną własną taką metodę, która zasłania
metodę dostępną w klasie Figura.
To zjawisko właśnie nazywane jest polimorfizmem.
I teraz kolejna bardzo ważna sprawa. Jest to słowo kluczowe this, które pojawia się w JavaScript, ale także
pojawia się w bardzo wielu innych językach programowania, które są zorientowane obiektowo. Słowo this
będzie nam kierować na obiekt, na którym aktualnie pracujemy.
Więc wyobraź sobie znowu, że mamy klasę Figura i mamy metodę obliczObwod. I chcemy, aby ta metoda nam
zwróciła np. długości wszystkich boków
+ .sum.
To jest pseudokod, więc zakładam, że dlugosciBokow.sum po prostu zsumuje nam tablicę z bokami. Natomiast
na czerwono zaznaczyłem słowo kluczowe this. Czyli tworząc sobie taką klasę,
możemy się odwoływać w jej metodach do słowa kluczowego this i ono będzie kierować na odpowiedni obiekt
utworzony z tej klasy.
Więc spójrzmy na przykład, jeżeli utworzymy sobie figura1,
mamy tutaj jakieś dane podane. Teraz będziemy chcieli się odwołać do figura1.obliczObwod(),
to klasa będzie wiedzieć, że słowo this ma kierować właśnie na ten konkretny obiekt.
Natomiast możemy utworzyć drugą zmienną, która będzie się nazywała figura2.
I na niej również będziemy mogli wywołać
figura2.obliczObwod()
i tutaj zostaną nam też zwrócone poprawne dane. Czyli to, co widzisz u dołu, są to utworzone już
instancje obiektów
i właśnie słowo kluczowe this w odpowiednim momencie kieruje na odpowiednią instancję,
kiedy taka metoda jest wywoływana. Na sam koniec chciałbym przejść już do języka JavaScript i pokazać
ci prosty przykład.
Wiesz, że możemy np. na jakimś elemencie div zarejestrować zdarzenie kliknięcia. Omawiałem to szczególnie
w pierwszej części kursu JavaScript od podstaw. I wiesz, że możemy tam przechwycić taki event.
Tutaj sobie go zapisujemy w zmiennej e i np. wyświetlić sobie, tak jak tutaj widzisz w konsoli,
e.offsetX. I teraz mógłbyś się zastanowić, skąd w ogóle w tym obiekcie event jest tak wiele różnych
informacji, tak wiele właściwości czy metod.
Skąd one się wzięły
w przypadku języka JavaScript?
Otóż taki obiekt event, który tutaj widzimy, to jest to instancja utworzona z konkretnej klasy - np. jeżeli
chodzi o kliknięcie z klasy, która nazywa się MouseEvent. Więc za naszymi plecami, kiedy klikamy na taki
element, tworzony jest nowy obiekt z takiej klasy MouseEvent, która ma różne właściwości, np. takie jak
offsetX.
One są uzupełniane odpowiednimi danymi i jest to nam zwracane w postaci takiego obiektu, na którym możemy
operować.
Mam nadzieję, że trochę z tej lekcji wyniosłeś. Poznałeś najważniejsze paradygmaty programowania zorientowanego
obiektowo, które przydadzą ci się w nauce programowania obiektowego
w każdym z języków programowania. Więc w razie potrzeby wróć sobie do tej teoretycznej lekcji, a od kolejnej
lekcji przejdziemy już do tego, jak możemy programować obiektowo w języku JavaScript i jak to się różni
od tego, co pokazałem ci w tej lekcji.