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.
W tej lekcji poznasz kolejną konstrukcję, która nazywa się WeakSet i w zasadzie działa
tak samo jak set, natomiast jest słaba i co to oznacza. Teraz
będę chciał ci pokazać. Mam dwa takie oto obiekty i chciałbym sobie utworzyć nowy
WeakSet, więc napiszemy sobie let może s new WeakSet,
czyli tak samo jak Set, ale mamy tutaj jeszcze słowo Weak
na początku tej nazwy i teraz do tego set'u będziemy chcieli sobie dodać
person 1 i person 2. Moglibyśmy też to zrobić przy
tworzeniu takiego set'u, ale dodajmy sobie to w taki sposób i
teraz zobaczymy w przeglądarce co jest pod s. Tutaj
zobaczymy, że mamy 2 takie obiekty. Natomiast powiem ci od razu jedną ciekawą rzecz. Otóż WeakSet nie
jest iteratorem, czyli nie możemy iterować po dodanych do niego obiektach
czy różnych innych wartościach. Natomiast to co jest ciekawe to do set'u mogliśmy dodawać wszystko, a
do WeakSet'u nie. Co by było gdybyśmy do WeakSet'u próbowali dodać
wartość prymitywną, taką jak na przykład Piotr. Okaże się, że to generuje błąd. Dlaczego
tak jest, powiem ci za moment, natomiast zapamiętaj, że możesz do WeakSet'u dodawać
wyłącznie obiekty i to nie znaczy, że to muszą być obiekty takie jak tutaj, ale
to oznacza, że muszą to być nie wartości prymitywne, czyli w JavaScript'cie wszystko
co nie jest wartością prymitywna jest obiektem i tutaj nie można po prostu dodawać
wartości prymitywnych. Weakset nie jest również iteratorem czyli nie możemy
właśnie iterować po wszystkich jego dodanych wartościach i nie możemy
też sprawdzić właściwości size, aby dowiedzieć się ile w nim jest elementów. Tak
naprawdę to co możemy zrobić, to możemy do niego dodać jakiś element i możemy ten
element usunąć, czyli mamy metodę add, delete i mamy też metodę has. Zatem
możemy jakiś element dodać, sprawdzić czy tam jest albo go usunąć. Nie mamy tutaj
też metody clear, więc wydawałoby się że taki WeakSet jest troszeczkę bezużyteczny,
ale teraz powiem ci najciekawszą rzecz na jego temat. Otóż jeżeli
dodamy coś do takiego WeakSet'u i później stracimy referencje do danego obiektu,
to jest on również usuwany z WeakSet'u. Innymi słowy,
jeżeli teraz sobie podejrzymy s, odświeżmy, tutaj muszę zapisać. To
widzimy, że w środku konsola przeglądarki pokazuje nam że mamy dwa takie obiekty. Natomiast,
jeżeli stracimy referencję do obiektu, czyli napisałbym na przykład person
1 równa się null to w JavaScripcie nie mamy możliwości już odwołania
się do tego obiektu i w tym miejscu wkracza do gry tak zwany garbage
collector, czyli odśmiecacz i on w pamięci może taki obiekt usunąć. Dlaczego
tak się dzieje. Otóż skoro nadpisałem zmienną person 1 wartością null
czy jakąkolwiek inną wartością mógłbym nadpisać, to najciekawsze jest to, że
w tym momencie nie ma już tego obiektu. Ja miałem ten obiekt przypisany tutaj. Nigdzie
go nie przekazałem. Nigdzie go nie przypisałem do innej zmiennej, więc można
to zobaczyć na logikę. Jeżeli napiszę coś takiego, nie mam już żadnej możliwości, żeby
wrócić do tego obiektu. Zatem garbage collector javascriptowy może ten obiekt
usunąć, bo tak jak wspomniałem, nie ma z naszego kodu możliwości do niego się odwołania. Podobnie
byłoby w funkcji gdybyśmy mieli jakąkolwiek funkcje i w środku tej funkcji tworzymy
zmienna let z równa się 1, to w momencie kiedy
wywołujemy taką funkcję taka zmienna jest tworzona, ale nie zwracamy jej. Nic
z nią nie robimy, więc kiedy ta funkcja się zakończy, nie ma możliwości dostać
się do tej wartości, dlatego garbage collector też ją może usunąć, czyli podobnie
będzie w tym przypadku jeżeli napiszę tutaj person 1 równa się null. No i teraz
najciekawsze jest to, że właśnie kiedy stracimy referencje do danego obiektu i
też z tego powodu tylko obiekty mogą być w tutaj przekazywane. Bo do zwykłego
set'u to mogłem sobie dodać na przykład imię Piotr, ale jest to wartość prymitywna, która jest
kopiowana. Natomiast obiekty są przekazywane przez referencje, czyli jeżeli tutaj
przekazałem person 1, to go nie skopiowałem tylko wstawiłem go do WeakSet'u. Tutaj
straciłem już do niego uchwyt, nigdzie indziej go nie mam. Garbage collector może
go usunąć i co ciekawe usunie go również z tego WeakSet'u. Możemy
sobie to sprawdzić. Gdybyśmy teraz odświeżyli i napisałbym s, to
cały czas to jeszcze tutaj widać, bo garbage collector niekoniecznie uruchamia się od razu
kiedy taka wartość nam zniknie, ale za moment zobaczymy, że ona rzeczywiście zniknie. Natomiast
nie mogę z tego WeakSet'u wyciągnąć już tej wartości person 1, bo wspominałem
ci, że on nie jest iteratorem, nie można po nim iterować, czyli żeby z niego coś
wyciągnąć, to żeby dowiedzieć się w zasadzie, że tam coś jest, to nawet wyciągnąć
nie możemy, to musiałbym napisać w tym momencie s has. No właśnie
i przekazać ten obiekt, ale pod person 1 mam już teraz tylko null, więc
jak widzisz nie mam żadnej możliwości, żeby tam się dostać. Dlatego jeżeli byśmy
jeszcze raz sobie to sprawdzili. Kilkukrotnie jeżeli to sprawdzimy, to po jakimś czasie zostanie to
usunięte. Może utwórzmy jakąś zmienną. Tak
żeby coś ten interpreter JavaScript'u zrobił. No właśnie i teraz zajrzyjmy sobie do WeakSet'u. Jak
widzisz zniknął nam całkowicie ten obiekt, który przechowywany był pod zmienną person
1. Co by było jednak gdybym tutaj napisał sobie let
person 3 równa się person 1, wtedy jeżeli person
1 nadpiszę na wartość null, to tak naprawdę tracę ten obiekt,
ale chwila, ja sobie go przepisałem również do person 3, on nie został tutaj skopiowany,
tylko referencja do niego została przypisana, więc garbage collector go nie usunie i
nie zniknie on też z WeakSet'u, bo w każdym momencie mogę napisać tutaj na
przykład console.log s has person 3, to nie ma znaczenia, że
to jest inaczej nazywana zmienna, bo tutaj przekazujemy to, co ona ma w
sobie, a ona w sobie ma referencje cały czas do tego obiektu, więc zobaczmy,
mamy wartość true i dopiero teraz gdybym napisał person 3 równa się null,
to tak naprawdę teraz znowu straciłem uchwyt do tego obiektu i garbage
collector dopiero teraz mógłby go usunąć i teraz najważniejsze być
może masz tak samo jak ja miałem na początku kiedy zobaczyłem WeakSet, że w sumie fajnie, że
tak to działa, ale jakie może być tego praktyczne zastosowanie. Ja przyznam
się, że tak na codzień z tego nie korzystam, ale znalazłem w internecie ciekawe zastosowanie,
dlatego teraz będę chciał ci je pokazać. Przejdziemy sobie pod pewien adres,
tutaj i tutaj
jest pokazane jak można z tego skorzystać. Ja ten kod sobie skopiowałem i delikatnie zmodyfikowałem. Natomiast
pokazuje ci gdzie on jest, żeby nie było, że ja go wymyśliłem, bo po prostu znalazłem
go robiąc research do tego kursu. Zróbmy sobie tak, że to wszystko wykomentuję i
wkleję tutaj taki fragment kodu, czyli
będziemy mieli tutaj utworzone nowy WeakSet pod stałą people i
teraz utworzyłem sobie klasę, to już znasz i zauważ, co robimy kiedy utworzymy
nowy obiekt klasy w konstruktorze. Otóż this będę chciał dodać sobie do
tego nowego set'u, czyli w tym secie będzie każdy nowy utworzony obiekt w tej
klasy person i teraz na prototypie dodajemy metodę sayHello, w której
sprawdzamy czy people zawiera this, czyli obiekt,
na którym to wykonaliśmy. Jeżeli nie, to będziemy chcieli wyrzucić błąd, że Person prototype sayHello
została wywołana na niekompatybilnym obiekcie. Na razie się to wydaje głupie,
ale zobaczysz zaraz jak będziemy mogli to sprowokować. Jeżeli ten if
się nie wykona, to normalnie zrobimy sobie return firstName i lastName. Utworzyłem
sobie teraz new Person Jan Kowalski i spróbujmy zrobić w konsoli person 4
sayHello. Prześledźmy teraz jeszcze, w momencie
kiedy robimy new Person, wywołuje się ten konstruktor i mamy tutaj w środku this,
jest to nowy obiekt. Dodajemy sobie go do people, czyli do tego WeakSet'u
i teraz jeżeli wywołam sayHello na tym konkretnym obiekcie, to
sprawdzimy czy on jest w tym WeakSecie. Jeżeli jest, to ten, ta instrukcja
się nie wykona, czyli normalnie zwrócimy sobie imię i nazwisko.
Jak widzisz tak też się stało, ale gdybyśmy teraz próbowali sobie pożyczyć metodę
sayHello od tego obiektu, w taki sposób już tutaj wkleję kod. Utworzylibyśmy
sobie taki prosty obiekt i wiesz, że możemy pożyczyć dowolną metodę odwołując
się do Person prototype sayHello, czyli do tej metody i metodą call
chcę ją wywołać, mówiąc co ma być pod this wewnątrz, czyli pod this
chciałbym mieć person 5. To powinno sprawić, że tutaj this firstName
będzie kierować na to firstName i lastName na to. Zobaczmy, zobaczymy
błąd, że Person prototype sayHello wywołana na niekompatybilnym obiekcie. Gdybym
sobie jednak usunął tę instrukcje, to wszystko byłoby w porządku. Jak widzisz Anna
Nowak by się wywołała, czyli w zasadzie może być to takie praktyczne zastosowanie
WeakSet'u, dlatego że jeżeli chcemy, aby tylko obiekty utworzone
konkretnie z tej klasy mogły korzystać z jej metod, to możemy to zrobić w ten sposób dlatego
że tutaj person 5, czyli ten obiekt wpadł pod this i sprawdziliśmy
czy w tym secie on się znajduje. Okazało się, że nie, bo nigdy nie był
tak naprawdę jakby w tej linijce. No i dlatego zwróciliśmy taki błąd. Natomiast
dlaczego plusem jest, że jest WeakSet. No właśnie dlatego, że przy tworzeniu nowego
obiektu jest on dodawany do WeakSet'u i mamy go tutaj, person 4, ale
gdybym sobie teraz napisał person 4 równa się null. Znowu
utraciłem referencje do tego obiektu i nie będziemy niepotrzebnie w pamięci przechowywać
tego this, bo zapychałoby nam to pamięć, a my już i tak nie mamy żadnych
szans, żeby się do tego obiektu gdziekolwiek w kodzie odwołać. Więc dzięki temu, że jest to WeakSet,
to garbage collector po pierwsze usunie nasz obiekt. W ogóle tutaj, bo go jakby
nadpisałem jakąś inną wartością, a po drugie sprawdzi, że w WeakSecie ten obiekt
był i również go usunie, czyszcząc pamięć. Jak zatem widzisz
WeakSet to ciekawa konstrukcja, aczkolwiek być może nie znajdziesz na co dzień dla
niej praktycznego zastosowania. Niemniej jednak dobrze, że się pojawiła. Podobnie
jak set, chociaż set będzie bardziej przydatny. Natomiast w następnej lekcji poznasz
coś, co będzie wydaje mi się jeszcze bardziej przydatne niż na przykład set, a jest
to map.