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.
Wiesz już naprawdę dobrze, jak działają iteratory i jakie są z nich korzyści. Przede
wszystkim to, że możemy wykorzystywać na nich operator spread, a także pętle
for of. Natomiast tworzenie iteratorów, jak widziałaś może być dosyć
takie skomplikowane, bo musimy stworzyć tam metodę next, która nam to wszystko zwraca i
tak dalej. Dlatego teraz poznasz generatory, a są to funkcje,
które zwracają iterator i pozwalają nam zupełnie inny sposób w tym wszystkim
pracować. Natomiast wiedząc już, że każdy taki obiekt zwracany z
next musi mieć done i value, zobaczysz, że generatory działają dokładnie
w taki sam sposób. Przejdziemy sobie od razu do kodu i utworzymy sobie swój pierwszy
generator. Tworzymy go normalnie tak jak każdą funkcje, ale od razu powiem
ci, że nie może być utworzony z funkcją strzałkową, czyli z arrow function, więc
musi to być taka zwykła funkcja albo w obiekcie ten skrócony zapis funkcji. I teraz
tutaj normalnie mielibyśmy nazwę na przykład it, to przed nazwą stawiamy gwiazdkę,
tutaj. I teraz gwiazdka może być postawiona w ten sposób, w ten
sposób, w ten sposób lub w ten sposób, nie ma znaczenia. Między function, a
nazwą powinna być gwiazdka, chyba że będzie to funkcja anonimowa, to wtedy
wygląda to mniej więcej tak, tak też powinno działać. Nasza nazywa
się it jak iterator i w ten sposób sobie ją utworzymy. I to
co jest niesłychanie ważne, teraz jeżeli wywołam tę funkcje, to ona mi zwróci iterator,
czyli zobaczmy, napiszę sobie let iterator równa
się it i ją po prostu wywołam. Natomiast to być może nam wygeneruje
błąd, okej, tak się nie stało, dlatego że ta funkcja powinna w sobie zawierać
specjalne słowo yield, ale o tym za moment. Jednak co się stało? Co
jest pod zmienną iterator? Zobaczmy. Zobaczymy,
jest to jakiś obiekt it, który ma w sobie generator status suspended. Nie
ma to dla nas do końca teraz znaczenia, ale ważne jest to, że kiedy masz funkcję generatora,
taką z gwiazdką i raz ją wywołasz, to on zwróci iterator. To
znaczy, że ten obiekt iterator zawiera w sobie metodę next, którą wcześniej
musieliśmy tworzyć sami. Taka metoda tutaj być powinna i spróbujemy ją wywołać. Nie
ma żadnego błędu, więc zobaczmy co ona do console log'a nam mogła zwrócić. Jak
widzisz, zwraca obiekt, który ma value undefined i done true. To jest dokładnie
to, co my ręcznie zwracaliśmy, bo tego oczekuje zawsze iterator, czy w
zasadzie coś co korzysta z iteratora, na przykład pętla for of. Ona korzysta
z takiego obiektu, wyciągając sobie value i sprawdzając czy done
ma też już wartość true, czyli na przykład czy zakończy iteracje. Podobnie z resztą operator
spread. Dlaczego tutaj jest done true? Dlatego, że nic w tej
funkcji nie zwróciliśmy i teraz to co jest ważne, funkcje generatora korzystają
ze specjalnego słowa, które tylko w takiej funkcji jest dostępne, jest
to yield. Wygląda to tak i działa troszeczkę tak jak
return. Jeżeli napisze yield jeden. Zobaczmy, co się stanie. To
ten obiekt teraz ma value 1 i done jest to false, więc
teraz jeżeli raz jeszcze byśmy wykonali, to się okaże, że value to już jest undefined
i done to jest wartość true. Takich yield'ów może być w generatorze więcej. Tutaj
może być dwa, trzy i powiedzmy tyle sobie i zostawimy
i to skopiuj jeszcze kilkukrotnie i zauważ, że każde kolejne użycie next zwraca
nam kolejną wartość z yield właśnie w takim obiekcie, pod kluczem value,
a kiedy nie ma już kolejnego yield'a, to jest zwrócone undefined i done ustala nam
wartość true. Wiem, że to wygląda dziwnie, ale jest jedna bardzo ważna rzecz,
jeżeli chodzi o funkcję generatorów. Otóż one są pauzowane, to znaczy,
że ta funkcja robi pierwszy yield kiedy użyjemy tutaj iterator next. Zobaczmy,
zwróci nam tą jedynkę i ona nie przejdzie do kolejnej linijki wykonywania,
aż do tego czasu, aż do czasu aż nie wykonamy iterator next, czyli ta funkcja potrafi
się zapauzować i nie przechodzi do kolejnej linijki. Co ciekawe, w tej funkcji, oczywiście
może być wszystko, tworzenie zmiennych i różne inne operacje, nie tylko same yield'y. Więc
można taką funkcję zapauzować, w ten sposób, że nie wykonujemy kolejnego
next'a i ona wtedy nie wykona kolejnego kodu. I nie chodzi do końca o linijkę,
bo jeżeli zrobie sobie yield i później tutaj będzie kilka
jakichś linijek, to kiedy wykonamy next, to kilka linijek zaraz będzie wykonanych. Chodzi
o to, że ona pauzuje od jednego yield'a do drugiego, więc teraz sobie to
wykomentujmy i pokażę ci inny przykład. W środku takiej funkcji zrobimy sobie
pętle for of i napiszemy let i równa
się 0. W zasadzie będzie to pętla normalna, nie for of,
i jest mniejsze lub równe 50, może od jedynki sobie zróbmyi i
plus plus i zrobimy sobie tutaj wewnątrz yield
i. I wydawałoby się, że ta pętla się wykona 50
razy, ale zobaczmy czy tak będzie. Okazuje się, że nie, że wyłącznie raz, czyli
dopiero, kiedy następnym razem zrobimy iterator next i next, to ona wykona
kolejne iteracje, czyli potrafi nawet zapauzować pętlę, która jest w jej
wnętrzu i tutaj znowu nie będziemy sobie wykonywać next ręcznie,
bo nie jesteś to zbyt użyteczne, ale pamiętasz, że takie next może
za nas wykonać czy to operator spread czy na przykład pętla for of, więc
spróbujmy taką pętle sobie zrobić, for i napiszemy sobie let, na
przykład, value of iterator, console.log value. Od
razu z tego obiektu kropka value będzie wyjęte, oczywiście nazwa tej zmiennej,
nie ma z tym nic wspólnego i zauważ, że teraz od 1 do 50, wszystkie
wartości zostały wyświetlone dlatego, że właśnie ta pętla będzie wykonywać
iterator next tak długo, aż nie zostanie zwrócony obiekt, w którym done ma wartość
false. A to zostanie zrobione automatycznie. Oczywiście
chodzi o done wartość true, a nie false. To zostanie zrobione automatycznie, kiedy nie ma już kolejnego yield'a,
bo ta pętla się zatrzymała. Zapewniam cię, że jeżeli jeszcze nie
widzisz konkretnych zastosowań, to w kolejnych lekcjach je zobaczysz, ale chciałbym ci teraz pokazać kolejną
rzecz. Otóż jak do naszego własnego obiektu moglibyśmy sobie dodać
iterator, nie tworząc tej metody, którą mieliśmy wcześniej czy nie, konkretnie metody
next. Może zróbmy sobie to w tym miejscu, będziemy mieli
jakiś obiekt, który nazwę it i wewnątrz, pamiętasz, pod symbol kropka
iterator dodawaliśmy sobie iterator,
tylko, że on musiał zwrócić obiekt, w który ma metodę next i tak
dalej. Natomiast, jeżeli teraz na początku takiej wyliczonej właściwości napiszemy gwiazdkę,
tutaj jest ona na początku, jak widzisz, a nie gdzieś tutaj pomiędzy, to cały
ten symbol iterator będzie funkcją generatora, czyli kiedy na przykład taka
pętla for of będzie szukała iteratora, to go znajdzie, ale
dodatkowo będzie to generator. Skoro jest to generator, to może korzystać z yield'ów i
on automatycznie zadba o to, żeby zwracać ten obiekt, który ma value i done, więc
utwórzmy my sobie tutaj tablicę numbers i niech
nie będzie jeden, dwa, trzy, cztery i pięć i pamiętasz, jeżeli
nie, to wróć do poprzednich przykładów, gdzie ja to zwracałem taką metodą next, którą sami
napisaliśmy. Teraz nie musimy tego robić, wiemy, że ta tablica ma
w sobie iterator, więc można na niej wykonać pętle for of. Czyli
napiszmy sobie, na przykład, number of numbers i będziemy
chcieli robić yield, number. Znowu
ta pętla będzie pauzowana, więc będzie musiało być wykonany znowu iterator next i
tak dalej, i tak dalej. Natomiast zrobi to za nas już interpreter JavaScript'u,
odpowiednio to wszystko wywoła, więc teraz napiszmy sobie for let value
of i podam nasz obiekt it. Tylko zobaczmy czy to wystarczy. Jak
widzisz, jak najbardziej, czyli nie muszę już, tak jak ci pokazywałem wcześniej, tutaj
wywoływać sobie tej funkcji iteratora czy funkcji generującej, żeby mi zwróciła
iterator. Teraz, jeżeli on jest dodany w formie właśnie generatora,
pod symbol kropka iterator, to jeżeli na takim obiekcie wywołam sobie
metodę it czy w zasadzie przepraszam. Jeżeli wywołam sobie pętle
for of, na tym obiekcie, to automatycznie zostanie w środku znaleziony
generator, pod symbol kropka iterator. On zostanie wywołany,
on nam zwróci obiekt, który będzie miał metodę next. No i ta metoda
będzie wykonywana aż do skutku. Gdybym tutaj dodał oczywiście jeszcze szóstkę, zapiszmy,
to ona się tutaj pojawi. Więc jest to rzeczywiście nowa koncepcja.
Jeżeli do tej pory nie widziałeś, w innych językach programowania czegoś
takiego. Natomiast bardzo fajnie, że zawitała do JavaScript'u, bo ma jeszcze wiele innych ciekawych
zastosowań, o których dowiesz się później. Na końcu pokażę ci jeszcze jeden ciekawy
przykład, który moglibyśmy sobie tutaj wykonać. Gdybym chciał stworzyć taką konstrukcję jak range. W
niektórych językach jest dostępna, w języku JavaScript jej nie mamy, to utwórzmy sobie
funkcję generatora, czyli z gwiazdką, którą nazwiemy range i tutaj będzie from
to, czyli od do. Chciałbym móc podawać na przykład od 2 do 10,
coś w tym stylu i zróbmy sobie coś takiego, let i równa
się from, czyli na początku będzie to taka wartość i wykonamy sobie pętle while i
tak długo jak i jest mniejsze lub równe to, czyli do, to
będę chciał robić yield, i plus plus, czyli
najpierw zostanie zwrócona wartość i, a potem zwiększona o 1. W ten sposób będziemy
tutaj jakby taką pętle wykonywać, tak długo aż nie osiągniemy tej wartości, która
jest w tym miejscu, okej i teraz sobie w pętli for of będziemy
mogli z tego skorzystać. Napiszmy sobie let value of i zobacz,
wykonamy sobie range, podając 2 i na przykład 13
i teraz przejdźmy dalej i wyświetli my sobie value. Zobaczmy
raz jeszcze, co tutaj się stanie. Na początek interpreter wywoła
sobie funkcję range, a mówiłem ci, że kiedy wywołujemy sobie funkcje generatora,
to ona zwraca iterator, więc w tym miejscu oczekiwany jest iterator i on
tutaj zostanie podstawiony. Mógłbym tu zapisać zmienne i podać tutaj zmienną, ale nie muszę. No
i będzie to iterator i wiemy, że ten iterator będzie działał tak, że będzie zwracał
nam wartość i, tak długo w tej pętli, która będzie pauzowania i uruchamiana
poprzez to wewnętrzne użycie next, tak długo aż nie osiągniemy wartości 13.
Sprawdźmy. Wartości od 2 do 13. Nie stworzyliśmy sobie taką
konstrukcji jak range, która działa na generatorach i zwraca oczywiście iterator. Zauważ,
że tutaj musieliśmy ten generator wywołać i on zwrócił iterator. Natomiast na przykład wyżej
na it nie musieliśmy tego wywoływać w żaden sposób, bo jeżeli jest to dodane
wewnętrznie poprzez symbol iterator, to interpreter sam sobie to wywoła i
zwróci sobie ten wewnętrzny iterator. Oczywiście zadziałałoby to podobnie gdybyśmy
tutaj zrobili it, symbol iterator i wywołali
sobie właśnie tę metodę. Sprawdźmy na koniec czy rzeczywiście by
to zadziałało i widzimy, że wartości są takie same. Po prostu nie musimy tego robić,
więc ja po prostu cofnę to do tej postaci i na tym sobie zakończymy
tą lekcję, a w kolejnej będziemy kontynuować poznawanie generatorów.