Nowy Standard JavaScript
10 godz. 43 min · JavaScript · Full-stack i Programowanie
Piotr PalarzWeb DeveloperNa początku dowiesz się jakie nowości pojawiły się w języku, jeśli chodzi o tworzenie zmiennych i stałych. Poznasz dwa nowe słowa let i const, a także dokładnie omówimy ich różnice, względem znanego nam do tej pory słowa var. Następnie poruszymy temat obiektów. Zobaczysz jak nowy zapis pozwoli znaczenie ułatwić nam pracę i sprawić, by kod był bardziej czytelny. W kolejnym rozdziale porozmawiamy o zmianach w funkcjach. Poznasz tzw. arrow functions wraz z poradami, kiedy z nich korzystać, a także z konsekwencjami ich użycia. Zobaczysz również, jak korzystać z domyślnych parametrów. Następną nowością będą operatory rest i spread, które znacząco uproszczą pisanie kodu dla funkcji i tablic. Chwilę później rzucimy okiem na bardzo ciekawy temat, mianowicie na tzw. destructuring. To nowa funkcja języka, która pozwala w łatwy sposób wyciągnąć odpowiednie dane z tablic i obiektów, nawet jeżeli te posiadają kilkupoziomową, zagnieżdżoną strukturę. Zmian doczekały się również ciągi znaków. Poznasz nowy zapis, tzw. template string, a także możliwość wykorzystania funkcji tagujących.
ES6 wprowadza do języka JavaScript zapis klas. I choć na początku wydaje się, że to duży krok w stronę klasycznych obiektowych języków programowania, to jak się przekonasz, jest to w dużej mierze tzw. syntactic sugar, a więc zupełnie nowy, prostszy zapis, a prawie identyczne jak wcześniej działanie, oparte na dziedziczeniu prototypowym. W kursie poruszymy również temat Symboli oraz tego jak z nimi pracować, a chwilę później poznasz iteratory. To konstrukcje ułatwiające iterację, które znacząco upraszczają pracę z kolekcjami danych. Wraz z iteratorami poznasz również generatory, które ułatwiają z kolei tworzenie tych iteratorów. Istotną nowością w ES6 są również natywne Promise. To sposób na rozwiązanie problemu asynchroniczności, który znamy od bardzo dawna w postaci różnych bibliotek. Od teraz jednak Promisy znajdują się bezpośrednio w języku. Nowymi konstrukcjami, które pozwalają pracować z kolekcjami danych, są Map i Set. Dowiesz się jak z nich korzystać, a także do czego są przydatne. W jednym z rozdziałów rzucimy też okiem na tzw. Proxy API. To mechanizm języka, który pozwala na dość niskopoziomowy dostęp do różnych operacji. I choć być może nie jest to coś, z czego będziesz korzystał nad wyraz często, to warto wiedzieć, jakie są nowe możliwości tego API.
Jedną z najlepszych nowości, która zawitała do języka JavaScript wraz z ES6 są moduły. To możliwość dzielenia kodu na wiele plików, z których można pewne wartości wyeksportować, a następnie zaimportować je w innych modułach. Tutaj dowiesz się wszystkiego, co z modułami związane. Zobaczysz wiele sposobów na eksport i import, a także jak pracować z modułami w przeglądarkach internetowych. Kurs skupia się na omówieniu wszystkich najważniejszych nowości w ES6, dzieląc je na rozdziały. Jeden z nich natomiast, poświęcony został omówieniu mniejszych zmian, które znalazły się w specyfikacji. Poznasz w nim np. nowe metody tablic czy ulepszoną współpracę z Unicode.
Specyfikacja EcmaScript 2015 wprowadziła naprawdę bardzo wiele zmian, ale jej twórcy założyli, że od tego czasu każda kolejna wersja specyfikacji będzie pojawiać się co roku. Oznacza to przede wszystkim, że nie będziemy na raz bombardowani aż tak wieloma zmianami, jak w 2015 roku. W tym kursie nie zabrakło zatem omówienia nowości ze specyfikacji ES2016 oraz 2017, gdzie poznasz np. nowe metody dla stringów czy funkcje asynchroniczne.
Kiedy będziesz już uzbrojony w solidną wiedzę z zakresu nowości w ES6, dowiesz się jak w praktyce pracuje się dzisiaj z tym standardem. W jednym z rozdziałów omówimy nowoczesny workflow z użyciem npm i wykorzystamy popularne narzędzie webpack, do pracy z modułami, a także do transpilowania kodu ES6 do wersji ES5. Dzięki temu nowoczesny kod, który napiszemy, będzie mógł być uruchamiany również w starszych przeglądarkach, które nie wspierają najnowszego standardu. Dowiesz się na co zwrócić uwagę, by wszystko działało bez zarzutu.
Zwieńczeniem tego kursu będzie praktyczny projekt, w którym od podstaw wykonamy swoją własną bibliotekę do pracy z Obiektowym Modelem Dokumentu. Będzie ona w działaniu nieco podobna do znanej chyba wszystkim biblioteki jQuery. Na tym przykładzie postaramy się wykorzystać jak najwięcej wiedzy z zakresu ES6 zdobytej wcześniej. Stworzymy metody do pracy z drzewem dokumentu, a więc do wyszukiwania elementów, do tworzenia nowych, do przypisywania im klas, atrybutów czy styli CSS. Nie zabraknie również modułu odpowiedzialnego za współpracę z Ajax. Cały kod utworzymy oczywiście w sposób modułowy, aby bibliotekę można było łatwo rozwijać w przyszłości. Na koniec projekt ten przetranspilujemy do kodu ES5 z użyciem Babel i przetestujemy w starszej przeglądarce Internet Explorer 11, aby upewnić się, że nasza biblioteka działa poprawnie.
Kurs ten jest dla wszystkich osób, które znają już język JavaScript i czują się w pracy z nim swobodnie. Jeśli zatem chciałbyś pracować z nowoczesnym kodem JavaScript, to ten kurs jest zdecydowanie dla Ciebie. A może masz zamiar poznać framework Angular lub bibliotekę React? Tam również wykorzystywany jest najnowszy zapis ES6, więc wiedza ta będzie naprawdę pomocna. Z solidną wiedzą z zakresu EcmaScript 6, bez trudu pozostaniesz na bieżąco z każdą kolejną edycją tej specyfikacji.
Zobaczyłeś w poprzedniej lekcji jak działają tak zwane arrow function i kiedy
z nich można ewentualnie korzystać. Natomiast pytanie brzmi czy to jest
wyłącznie syntactic sugar, po raz kolejny, czyli czy tylko mamy uproszczony
zapis i wszystko działa dokładnie tak samo czy może jednak nie. Od razu
powiem ci, że nie i są pewne sytuacje, w których arrow function mają przewagę
nad zwykłymi funkcjami, a w innych sytuacjach po prostu nie nadają się do użycia i w
tej lekcji będę chciał ci pokazać kiedy. Przyjdziemy sobie do kodu i utworzyłem
sobie taki prosty literał obiektu, który ma metodę i jest
to sayHello. Zauważ, że utworzyłem ją za pomocą funkcji strzałkowej,
w taki oto sposób i chciałbym kiedy ją wywołamy, wyświetlić sobie po
prostu firstName i lastName połączone na spacji. Nie ma tutaj nic nowego. Gdyby
tutaj był taki zapis zwykłej funkcji, no to pewnie byłoby
to coś co wielokrotnie już widziałeś, więc jeżeli teraz zostawiłbym to z taką funkcją i w
konsoli napisał person sayHello, zobaczymy Jan
Kowalski. Zamieńmy sobie to jednak z powrostem na funkcje strzałkową i zobaczymy
czy efekt będzie rzeczywiście taki sam. Wywołuje sobie person sayHello
i otrzymujemy undefind i undefind i zastanówmy
się dlaczego. Widzimy tutaj, że this kropka firstName zwróciło undefind
i podobnie było w tym przypadku, a to oznacza, że słowo this nie kieruję
na obiekt, w którym znajduje się taka metoda. Dlaczego tak się dzieje? Otóż
nie da się ustawić kontekstu dla funkcji strzałkowej. Czyli nie ma możliwości,
aby wymusić, co ma się znaleźć tam pod this i automatycznie również
te wbudowane mechanizmy JavaScriptu, bo tutaj nic nie napisałem, co miałoby to wymusić,
ale oczekiwałbym tego od JavaScript'u, że tak to będzie działać. Też
tego nie ustawiają, czyli w takiej funkcji nie ma słowa kluczowego this,
ale gdyby całkiem go nie było to mielibyśmy błąd, więc pytanie brzmi, co kieruje
czy na co kieruje słowo kluczowe this. W tym przypadku ono kieruje na
takie this, które jest o jeden zakres wyżej niż zdefiniowana funkcja. Czyli
można powiedzieć, że this tutaj wewnątrz, to będzie to samo co this tutaj. Pytanie
czym jest this tutaj. Tutaj this jest to globalny obiekt, czyli
w przeglądarce window. No bo mamy ten skrypt nieopleciony niczym
innym, gdybym go oplótł jakąś funkcją, generalnie działałoby to tak
samo. Możemy spróbować i zobaczysz, że rezultaty będą
takie same. No chociaż poza tym, że w sumie nie będziemy mogli wywołać
tej funkcji, bo nie mam dostępu teraz do person. Jeżeli to oplotłem, okej.
Więc teraz ci tego niestety nie pokażę, ale gwarantuję ci, że wyglądałoby to tak samo.
Skoro zatem this jest obiektem globalnym, to gdybym sobie utworzył
zmienną za pomocą var, na przykład firstName, to pokazywałem ci już wcześniej w lekcji
o var, że jeżeli utworzymy globalną zmienną i nie mamy tutaj żadnej innej
funkcji, na przykład Piotr, to ona zostanie dodana, tak jakby do window firstName.
No i to nam pokaże, że this firstName w tym miejscu rzeczywiście do tego window
first name się odwołuje. Spróbujmy napisać person sayHello i imię
tym razem jest to Piotr i teraz po co ci to pokazuje? Otóż
dlatego, że wydawałoby się, że jest to problemem, ale w wielu sytuacjach będzie to zaletą.
Teraz chciałbym Ci pokazać taki przykład gdzie będzie to zaletą dlatego to wykomentuje
i wkleję sobie fragment innego kodu. Zróbmy
tak i na sekundę zamienię tylko tą funkcję
na normalną. Taki kod prawdopodobnie też już widziałeś, czyli kiedy wywołamy metodę
sayHello to chciałbym ustawić timeout i po jakimś czasie wyświetlić
sobie this firstName i lastName. Zauważ, że tutaj utworzyłem metodę w ten sposób,
a więc tak jakby to była funkcja, czyli wewnątrz tutaj this bezpośrednio
będzie kierować na ten obiekt. Czyli nie ma tego problemu, który jest wyżej. Tutaj będzie
to działać poprawnie, ale kiedy sobie dodam setTimeout i jeszcze jedną funkcję
ustawię do wykonania, to okaże się, że dla setTimeout, wewnątrz
jego this znowu będzie kierować na obiekt globalny. Mogę to udowodnić tutaj
odświeżając i robiąc person sayHello. Po dwóch sekundach nam się
metoda wykona i znowu mamy undefind i undefind. Chociaż w tym miejscu
this skierowało na poprawny obiekt. No i teraz jest wiele
możliwości obejścia takiego problemu. Jednym z nich jest na przykład zapisanie self
równa się this, powiedzmy, w tym miejscu albo that, często tak się pisze i
tutaj odwoływanie się do that. Wtedy oczywiście ma to sens i powinno
działać. Tutaj nam się dziś pojawił błąd. Okej mam dwie kropki. Natomiast,
jak sam widzisz, nie jest to najbardziej eleganckie rozwiązanie chociaż powszechnie cały
czas stosowane. Teraz mamy Jan Kowalski. Innym rozwiązaniem byłoby tutaj powrót
do this, ale żeby ustawić dla tej funkcji context to możemy
zrobić tak zwany bind. Jeżeli bindujemy funkcję, czyli wywołujemy na funkcji. Tutaj
jest cała funkcja, metodę bind. To bind zwraca jakby nową funkcję, którą jeśli wywołamy, to
wewnątrz this będzie kierować na to co podamy jako pierwszy parametr, więc tu mogę podać
co chcę, ale że podam this, bo jakby w tym miejscu jeszcze cały
czas jesteśmy jak w tym zakresie, this jest poprawne, więc jeżeli tak zrobię i wywołamy
sobie raz jeszcze tą metodę, to też okaże się po dwóch sekundach, że wszystko jest okej. Natomiast,
żeby nie kombinować to pokażę ci Jaka jest przewaga właśnie funkcji strzałkowej. Zamiast
pisać function tworzymy funkcje strzałkową, której nie da się wymusić this jak wspomniałem,
czyli setTimeout wywołując tę funkcję, nie wymusi, że this jest obiektem
globalnym, tylko ona będzie miała dostęp do this, takiego jak jeden zakres wyżej,
a że tutaj ten zakres jest poprawny, bo gdyby to była funkcja strzałkowa, no
to dokładnie tak jak tutaj byłby problem, ale że to jest zwykła funkcja, to tutaj this jest
poprawne, to i funkcja strzałkowa powinna mieć poprawne this. Wywołajmy
to sobie i raz jeszcze sprawdźmy. Jak widzisz, po dwóch sekundach Jan Kowalski
się pojawia w konsoli, więc wszystko jest okej. Widzisz zatem, że taka
funkcja może być bardzo przydatna, kiedy chcemy mieć dostęp do this albo
na przykład do zmiennej arguments, tak jak już ci pokazywałem, która jest jakby o jeden zakres
wyżej i nie chcemy, żeby jakiś mechanizm wymuszał użycie innego
this. Teraz pokażę ci jeszcze jeden przykład, że
nie możemy ustawić kontekstu i jak to wygląda, gdybym miał właśnie taki obiekt
person i tutaj na sekundę jeszcze zróbmy z tego normalną funkcję, tylko w takim skrótowym zapisie,
to wiemy, że wywołanie person sayHello zwróci nam Jan
Kowalski. Natomiast pod to this możemy podstawić coś innego i możemy
to wymusić, więc jeśli bym się odwołał do person kropka sayHello.
Nie wywoływał tej metody w ten sposób, ale za pomocą funkcji
czy metody call. Mam nadzieję, że też ją znasz. Ona generalnie zrobi to samo co
zrobiłaby, zrobiłby taki zapis. Czyli wywoła funkcję, ale
jako pierwszy parametr mogę podać to, co będzie pod this w takiej funkcji, więc
ja sobie tutaj wpiszę obiekt. To będzie this tutaj i w
tym obiekcie wpiszę firstName równa się, na przykład, Anna i lastName
równa się Nowak i oczywiście
to coś zwraca, więc chcielibyśmy to wyświetlić, dlatego ja to zawrę w console.log'u. Może
to nie wygląda aż tak elegancko, ale wiemy o co chodzi. No i widzimy Anna
Nowak, czyli mogłem wymusić sobie na funkcji sayHello, co ma być pod this
wewnątrz tej funkcji. Wymusić to można na trzy sposoby. Za pomocą call, apply
oraz metody bind i teraz czy można ustawić this jeżeli
byłaby to funkcja strzałkowa. Sprawdźmy. Zobaczmy
i będę miał wartość undefind oraz undefind. Czyli nie
da się zmienić this, chociaż nie generuje to błędu i metoda call na takiej funkcji jest dostępna
i działa, to nie da się za żadne skarby ustawić co ma się znaleźć
pod this w takiej funkcji i pod tym względem jest to zaletą tej funkcji, że
jeśli z niej korzystamy w takim przykładzie jak tutaj wyżej. Mamy pewność, że to this wewnątrz
nie będzie ustawione w żaden sposób przez funkcję setTimeout czy jakąkolwiek inną
do, której to zostało przekazane. Tylko zawsze będzie kierować na to, na
co kierowało jeden zakres wyżej. Jak zatem widzisz, w pewnych
sytuacjach jest to zaletą, ale na przykład może być wadą w taki sposób, że nie możemy
w ogóle z tej funkcji korzystać. Na przykład gdybyśmy chcieli przypisać
kliknięcie do jakiegoś przycisku. Mam tutaj na stronie przycisk kliknij mnie i on
się znajduje tutaj. Ma on identyfikator button 07, bo 07 to nasz
przykład i będę chciał do niego przypisać kliknięcie. Możemy go znaleźć
na stronie za pomocą document query selector, podając identyfikator
i możemy pisać do niego kliknięcie na wiele sposobów. Przypiszmy za
pomocą metody onclick, tak na szybko. No i normalnie jeżeli tutaj sobie jakąś
funkcję bym wstawił, to po wywołaniu tej funkcji, kiedy kliknę
na taki przycisk, to this będzie kierować dokładnie na ten element, na ten przycisk,
czyli będę mógł z nim zrobić co będę chciał. Czyli będzie to obiekt identyczny
jak zwrócone z takiego zapisu. Tutaj jeszcze otrzymamy pod parametrem e
zdarzenie event. Generalnie działa to tak, że e target
będzie nam zawsze kierowało na ten kliknięty przycisk. Na ten kliknięty
element i this również. Czyli gdybym zrobił takie porównanie przy e target, console.log. To
jest dokładnie to samo co this. Powinniśmy otrzymać true. Klikam
i widzimy w konsoli pojawia się true. Natomiast mogłoby nas tutaj kusić, aby przepisać
funkcję strzałkową, bo przecież mogłoby to być krótsze, szybsze i moglibyśmy
to zrobić w taki sposób i pytanie czy this,
to będzie dokładnie ten kliknięty przycisk. Myślę, że już
znasz odpowiedź, widzimy w konsoli false. Czyli jeżeli chciałbyś korzystać
przy przepisywaniu zdarzeń do elementów z funkcji strzałkowej, to owszem
możesz to robić, ale pamiętaj, że this nigdy nie zostanie ustawione na to
co cię interesuje, czy w zasadzie na ten przycisk czy jakiś inny element na
które wywołało się zdarzenie, ale będziesz miał tam dostęp do e target i znowu
są takie sytuacje w których będzie to dla ciebie przydatne, bo takie zdarzenie miało być
gdzieś w jakimś obiekcie, gdzie po kliknięciu na przycisk chciałbyś się odwołać do this,
które ma kierować na ten obiekt czy na jeszcze coś innego, a nie
na to na czym zostało wywołane zdarzenie. Więc czasami może to
być przydatne, po prostu ważne, abyś wiedział w jakich sytuacjach nam
to this nie zostanie ustawione. Generalnie przy funkcji strzałkowej this nigdy nie zostanie
zmienione. No i na koniec, pokażę ci jeszcze jeden przykład również
jest to bardzo istotne, aby o tym pamiętać. Zróbmy sobie coś takiego, wkleję
taki fragment kodu, czyli utworze sobie po prostu funkcje, ale tym razem strzałkową od
razu, która ma przyjmować firstName i zapisywać to w this firstName, czyli
stworzyłem konstruktor i teraz chciałbym utworzyć sobie nowy obiekt, więc napiszę
person1 new Person i podamy sobie
na przykład Anna. Gdyby to nie była funkcja strzałkowa, tylko normalna
funkcja. Po
odświeżeniu tutaj. Jeśli bym się odwołał do person1, mamy
firstName Anna. Nowy obiekt został utworzony. Natomiast zamieńmy to z powrotem
na funkcje strzałkową i zobaczymy co się stanie. Zobaczymy
w JavaScripcie błąd, person is not a constructor, czyli to jest kolejna
różnica pomiędzy funkcją strzałkową, a zwykłą funkcją. Nie można utworzyć z niej
nowych obiektów, czyli ona nie może być traktowana jako konstruktor. Z tego
powodu taka funkcja, nie zawiera również prototypu i gdybym chciał napisać consol.log person
prototype, to otrzymamy
tutaj undefind, czyli funkcje strzałkowe nie mają prototypu, nie ma możliwości
wymuszenia na nich co ma być pod słowem this wewnątrz ich ciała
i nie można z nich korzystać jak z konstruktorów. Jak widzisz są tego
zalety oraz wady i wszystko zależy już od twojego konkretnego użycia. Te
funkcje na pewno świetnie sprawdzą się przy filtrowaniu na tablicach, ale też wielu innych
sytuacjach gdzie chcemy mieć dostęp do this, które jest zdefiniowane jakby w o
jednym zakresie wyżej.