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 poprzedniej lekcji miałeś okazję zobaczyć w jaki sposób działa słowo kluczowe var w EcmaScript 5. Natomiast ES6
wprowadza dwa nowe słowa i jest to let i const i teraz pokażę ci czym
one się różnią i jak działają, a służą również do tworzenia zmiennych,
a także stałych. Zaraz się to wszystko wyjaśni, więc mamy taki przykład znowu
z jakąś funkcją, po to tylko, aby ograniczyć zakres zmiennych. Nie jest potrzebne, aby
były one widoczne w całej stronie internetowej, czyli w każdym innym miejscu w
kodzie JavaScript i teraz zamiast słowa kluczowego var użyjemy słowa let. Jest
to nowe słowo kluczowe, które służy do tego samego, co słowo
kluczowe var, więc nazwę sobie zmienną tak jak wcześniej firstName. Będziemy
operować na takich prostych nazwach i teraz jeżeli bym w konsoli chciał wyświetlić
sobie firstName. Oczywiście tutaj wszystko powinno działać tak jak
się tego spodziewamy. Widzisz tutaj wynik Jan. Natomiast co by było gdybym chciał
wyświetlić sobie firstName zanim ta zmienna została
utworzona. Od razu mój edytor podpowiada czy będzie to błąd. No i zobaczymy,
rzeczywiście jest to reference error i widzimy komunikat, że firstName
is not defined. To oznacza, że nie możemy korzystać ze zmiennych, tak
jak robiliśmy to w przypadku var, to znaczy innymi słowy, że nie działa tutaj zjawisko
tak zwanego hoistingu, czyli zmienne utworzone za pomocą let nie są wynoszone
na górę aktualnego zakresu. Nie możemy z nich skorzystać zanim
je nie zadeklarujemy i nie przypiszemy do nich jakichś wartości. W zasadzie
wartość nie jest konieczna, bo jeżeli zrobimy tak, to zmienna standardowo będzie mieć wartość undefind,
ale nie będziemy mieli już błędu. Innymi słowy widzisz jak to działa. Po prostu
nie możemy skorzystać ze zmiennej zanim jej nie utworzymy i ja
zostawię to z taką wartością. Kolejną mega istotną rzeczą, jeżeli
chodzi o tworzenie zmiennych z użyciem słowa kluczowego var jest
to, że są one przypisane do nowego zakresu. Jeżeli
jesteśmy na przykład w instrukcji warunkowej If lub w pętli. Mówiłem ci w poprzedniej
lekcji, że tylko funkcja może tworzyć nowy zakres zmiennych i jeżeli na przykład mieliśmy jakiś
warunek i w nim utworzyliśmy zmienną za pomocą var, to ona później była
widoczna wszędzie w tym zakresie. Natomiast, jeżeli skorzystamy z let i utworzymy
zmienną na przykład lastName, to
okaże się, że możemy z niej skorzystać tutaj w console.log. W przeglądarce nie
będzie żadnego błędu, wszystko jest okej. Natomiast jeżeli poza tym zakresem chcielibyśmy z niej
skorzystać, console.log lastName, otrzymamy reference
error lastName is not defined. Widzisz, jest to kolejna różnica,
jeżeli chodzi o słowo kluczowe let i var, czyli teraz takie nawiasy
klamrowe tworzą nowy zakres zmiennych. Nawet gdybyśmy je napisali w taki
sposób, to wydaje się, że po prostu tworzymy nowy literał obiektu.
Oczywiście gdybym tutaj napisał firstName równa się Jan, to utworzyłem nowy
obiekt, ale jeżeli tutaj bym sobie zrobił na przykład let age równa
się 30, to nie jest to już obiekt, ale jest to po prostu blok kodu,
który można w taki sposób również, gdybyśmy z jakiegoś powodu tego potrzebowali stworzyć
i nie będzie to błędem. Zobaczmy, błąd mamy tylko tutaj przy lastName,
bo on nam pozostał stąd. Natomiast sam taki zapis nie jest błędem, a ta
zmienna jest widoczna tylko w tym bloku kodu. Jednak rzadko będziemy z tego korzystać
w taki sposób, ale warto wiedzieć, że taki blok kodu, jak na przykład tutaj, ogranicza
nam zakres zmiennych i będzie podobnie w przypadku na przykład pętli, o
czym jeszcze powiem za chwilę. Kolejną istotną różnicą, jeżeli chodzi
o korzystanie z let jest to, że nie można drugi raz utworzyć takiej samej zmiennej.
Nie wiem czy wiedziałeś, ale za pomocą var, gdybyśmy napisali var na przykład
lastName równa się Kowalski. Gdybyśmy
drugi raz spróbowali napisać lastName Kowalski albo na
przykład Nowak i później to wyświetlić, to okaże
się, że nie jest żadnym problemem, po prostu nadpisaliśmy poprzednią wartość. Natomiast jeżeli
skorzystam tutaj z let, dwukrotnie. To po zapisaniu zobaczymy
w przeglądarce błąd właśnie, że zmienna została już wcześniej zadeklarowana.
Czyli znowu let jest tutaj bardziej rygorystyczne, co dla nas
tak naprawdę jest lepsze, bo jeżeli przez pomyłkę jeszcze raz utworzymy w tym
samym zakresie taką samą zmienną, z użyciem tego słowa, to otrzymamy błąd. Oczywiście
gdybym tutaj miał zakres ograniczony, tak jak tuta, pod spodem na przykład nowy
zakres, to w nim mogę utworzyć drugi raz zmienną o tej samej nazwie, czyli
gdybym to sobie wyciął i stworzył taki nowy zakres, nie powinniśmy mieć błędu
dlatego, że ta zmienna teraz jest przypisana wyłącznie do tego zakresu. Niemniej
jednak widzisz, że słowo let działa moim zdaniem lepiej niż słowo var
dlatego, że nie pozwala nam redeklarować zmiennych. Jeżeli na przykład ta zmienna
jest utworzona za pomocą firstName. a chciałbym ją nadpisać za pomocą var, też
otrzymam błąd, więc jeżeli raz ją utworzymy w ten sposób, nie możemy jeszcze
raz jej zadeklarować, nadpisać jej wartość oczywiście można, czyli firstName
zmienić na Kowalski, nie powinno być problemu. Błąd pojawia się tutaj wyłącznie
z tego consol.log'a. Jak widzisz, wszystko jest okej, bo cały czas jest zmienna,
czyli jest to po prostu taki placeholder, w którym przechowujemy jakąś wartość i
słowo zmienna oznacza, że można tę wartość zmieniać. Po prostu nie można jej
zadeklarować od nowa z użyciem żadnego ze słów jakie znamy. Teraz
chciałbym ci powiedzieć o czymś, co nazywa się TDZ, czyli Temporal Dead Zone. Jest
to taka tymczasowa strefa śmierci, można powiedzieć i jest to również zjawisko bardzo
ważne. Otóż mamy teraz tutaj te dwie zmienne. Ta, powiedzmy że i tak
w tym zakresie gdzie jesteśmy tutaj przy kursorze nie istnieje, ale gdybym chciał
operatorem typeof w konsoli sprawdzić sobie czy
istnieje zmienna, która nazywa się lastName, na przykład. To
otrzymam undefind, czyli typeof lastName to jest undefined. Ważne jest,
żeby pamiętać, że operator typeof to jest tak naprawdę jedyna konstrukcja, która pozwala
nam operować na zmienne, które nie zostało nawet zadeklarowane. Powiedzmy, że tego
bloku w ogóle nie ma, żebyś tutaj nie myślał, że to ma coś wspólnego jedno z drugim. Efekt
będzie dokładnie taki sam. Natomiast gdyby w ogóle wyświetlić lastName, a nie została
nigdzie zadeklarowana taka zmienna, to otrzymam błąd, czyli to pokazuje,
że typeof jest operatorem bezpiecznym, bo nawet jeżeli podam mu tutaj nazwy zmiennej, która
w ogóle nie została utworzona w żaden sposób, to on mi po prostu zwróci undefind. Natomiast
tak nie będzie jeżeli będziemy w tak zwanej Temporal Dead Zone i co
to oznacza. Jeżeli gdziekolwiek niżej chciałbym utworzyć zmienną za pomocą
let i ona miałaby mieć wartość czy w zasadzie nazwę lastName,
powiedzmy, Kowalski, to okaże się, że operator typeof
zwróci nam błąd, że lastName nie została zdefiniowana. Gdybym zrobił
dokładnie to samo za pomocą słowa kluczowego var, to
takiego błędu by już nie było. Czyli co to dla nas oznacza? Jeżeli wcześniej
w ogóle nigdzie w tym zakresie nie tworzyłem takiej zmiennej, to operator typeof był bezpieczny,
bo nigdzie takiej zmiany nie widział. Natomiast jeżeli taka zmienna jest
tutaj utworzona, to wszystko co jest nad nią jest nazywane poprzez TDZ, czyli Temporal Dead Zone i wtedy nawet
taki operator jak typeof zwróci nam, że zmienna nie została, tak
jak możesz zobaczyć zdefiniowana, bo interpreter JavaScriptu już wie, że ona
gdzieś tutaj poniżej jest, więc wszystko co jest nad nią jest tak zwanym Temperal Dead Zone. Gdyby
tego let nie było nagle okazuje się, że mimo tego, że taka zmienna nigdzie tutaj nawet w
planach nie jest, to nie ma żadnego błędu. Teraz pokażę ci
jeszcze jedną ciekawa rzecz jaką rozwiązuje użycie słowa let. Na
pewno wielokrotnie tworzyłeś pętle w ten sposób, tworzymy sobie zmienną i. Następnie
sprawdzamy na przykład czy i jest mniejsza od 10 i zwiększamy i. W tej
pętli coś byśmy robili, nie ma to większego znaczenia. Pamiętaj tylko, że jeżeli tutaj utworzyłbyś
sobie z użyciem słowa let jakiekolwiek zmienne, to plus jest taki, że one poza tym blokiem
już nie będą widoczne. Z var byłoby inaczej. Natomiast co dzieje się z samą
wartością i. Zobaczmy tutaj, console.log i, po
tym jak ta pętla się wykona 10 razy. Musimy sobie jeszcze
tylko to wykomentować, okej i zobaczmy, i ma
wartość 10. To jest kolejny efekt uboczny korzystania z var. Ja
chciałem sobie utworzyć tutaj zmienną i, która będzie wyłącznie w tej pętli widoczna. Nie
chcę żeby ona gdzieś była później możliwa do, tak naprawdę, korzystania
z niej, ale jak widać słowo var nie tworzy nam zmiennej przypisanej
wyłącznie do tej pętli. Podobnie będzie w pętli while, a także w każdej innej pętli. Dlatego
możemy tutaj również skorzystać ze słowa let i w tym momencie jeżeli będziemy
chcieli skorzystać poza pętlą ze zmiennej i, otrzymamy błąd, że taka
zmiana nie została zdefiniowana. To jest znowu kolejna fajna rzecz, bo tutaj i
będzie miało oczywiście wartość taką jak nas interesuje za każdym razem, ale
poza tym blokiem nie będzie już widoczna. Z korzystaniem właśnie
z takiej pętli for i ze słowem var wiąże się jeszcze jedna ciekawa historia, która często
jest pokazywana kiedy ktoś próbuje nauczyć
kogoś innego korzystania z let. Dlatego ja też chciałbym ci to pokazać. Wyobraź sobie że
utworzylibyśmy za pomocą var czy let tutaj to jeszcze nie ma znaczenia, tablice, w
której będziemy przechowywać funkcje i teraz chciałbym co nie jest dobrą praktyką,
ale chciałbym za każdą iteracją tej pętli, do tablicy, wstawić
nową wartość i żeby to była funkcja, czyli tutaj wpisuje funkcję anonimową. Tak naprawdę
ją definiując i chciałbym, żeby ta funkcja, kiedy ją wywołamy, żeby
robiła console.log wartość i to i dodamy
sobie do tego wartość, którą mamy tutaj, a więc utworzymy 10 takich funkcji i każda
z nich powinna mieć inną wartość i, czyli 0 1 2 3 i tak dalej. No
i teraz skoro mamy już taką tablice, tutaj po zakończeniu tej pętli, w
tej tablicy będzie 10 funkcji. To teraz każdą z nich chciałbym wywołać. Musimy znowu
jakąś iteracje przeprowadzić, więc między na przykład pętlą foreach na tablicach można
iterować. Podaje funkcje, która otrzyma jeden element w tablicy za każdym razem, czyli
na przykład nazwiemy go fn. Będzie to ta funkcja i będę chciał ją wywołać,
czyli tutaj przeliterujemy przez wszystkie funkcje dodane do tablicy i każdą z nich
spróbuję wywołać. Zobaczmy jaki będzie efekt i okazuje się, że 10 razy
został wyświetlony string wartość i to 10. Dlaczego
tak się dzieje? Otóż wydawałoby się, że ta funkcja tworzona tutaj za
każdą iteracją nowa, będzie mieć dostęp do tej unikalnej wartości i. Okazuje
się jednak, że domknięcie, bo tak to się fachowo nazywa, które tutaj jest tworzone. Jest
tworzone nie nad wartością, ale nad zmienną, więc jeżeli później po
całej tej iteracji zmienna ma wartość 10, to te funkcje wszystkie mają dostęp
do zmiennej o wartości 10, więc to jest taka pułapka, która w innym
przypadku, jeżeli ten kod troszeczkę inaczej by wyglądał, mogłaby dać ci w kość
i znowu ona jest rozwiązywana za pomocą let, bo let jakby za każdym razem
utworzy nową zmienną i to domknięcie zostanie jakby utworzone
nad tą nową zmienną. Zobaczmy jaka będzie różnica, jak widzisz, teraz każda
z tych 10 funkcji ma dostęp do innej wartości zmiennej i, bo
tak naprawdę ma dostęp do zupełnie innej zmiennej. Jak zatem widzisz,
korzystanie z let jest naprawdę ciekawe. Natomiast teraz będę chciał ci pokazać jeszcze jak
możemy korzystać ze słowa kluczowego const i teraz to co jest ważne. Słowo
kluczowe const zachowuje się dokładnie tak samo jak let, czyli nie ma zjawiska hoistingu,
tak samo by się zachowało w pętli i w każdej innej sytuacji, czyli wszystko
to co do tej pory wiesz o let. To samo tyczy się koń z jedną
tylko różnicą. Otóż, jeżeli utworzymy zmienną za pomocą const. Powiedzmy,
że napisałbym tutaj person i będzie to jakiś obiekt, który ma na przykład firstName Jan i
lastName Kowalski,
to nie możemy zmienić wartości takiej zmiennej. Mówiłem
ci przy let, że nie możemy jej jakby zadeklarować od nowa.
Tutaj jest tak samo, nie mogę napisać znowu person i zrobić czegoś takiego, ale okazuje
się, że nie mogę nawet nadpisać wartości tej jakby zmiennej. Chociaż w tym
przypadku jest to stała. Nie mogę jej w ogóle nadpisać, czyli w przypadku let. Jeżeli
coś sobie utworzymy, to mogę potem zmienić wartość tej zmiennej. W przypadku const, jeżeli
coś tutaj przypisze w ogóle się tego nie da zmienić. No i zobaczmy. Będę
miał błąd assigment constant variable, czyli nie możemy nic tutaj
nadpisać. Jest to dobre, jeżeli na przykład chcielibyśmy za pomocą const utworzyć sobie
powiedzmy taką zmienną czy stałą. Ja tutaj
operuje słowem zmienna, ale mam na myśli jakby tę konstrukcję, którą już znamy, ale
z const jest to stała, która tu będzie mieć jakiś na przykład adres http://mojastrona.pl
coś w tym stylu. To jest o tyle dobre, że mamy pewność, że nigdzie na szybko nie uda
nam się tego nadpisać przez przypadek na żadną inną wartość. Natomiast
jest jedna niesłychanie ważna rzecz. Nie da się do tej nazwy
person przypisać innego, ale to nie oznacza, że ten obiekt jest zamrożony
i że nie można go zmienić. Jeżeli odwołam się do person i na przykład firstName
i będę chciał to zmienić na Adam i później
wyświetlimy sobie cały obiekt pod stałą person. Okaże się, że nie ma problemu,
wszystko zostało zmienione. Tak więc zapamiętaj tylko tyle, że o ile to,
co jest tutaj przypisane można zmienić jeżeli jest to obiekt, o tyle
nie można zmienić tego co przypisujemy do samej nazwy person i na
koniec ostatnią rzeczą którą chciałbym ci pokazać jest fakt, że zmienne utworzone za
pomocą let czy stałe utworzone za pomocą const. Nie są dodawane do obiektu
window jako jego właściwości. Jeżeli tutaj w globalnym zakresie, całkowicie poza tą funkcją
napisałbym let firstName równa się na przykład Piotr. To
jeśli przejdziemy do przeglądarki, okaże się, że firstName jest tutaj dostępne globalnie. Natomiast
window firstName ma wartość undefined, czyli gdybym
to zrobił z użyciem var, tak jak widziałeś w poprzedniej lekcji to window firstName zwróciłoby nam
poprawną wartość. Natomiast z użyciem let czy const ta wartość
tutaj jest globalna, ale nie jest dodawana do window, więc tak naprawdę ona tylko przesłania
to co normalnie byłoby globalne tutaj. Innymi słowy jeżeli mamy jakąś
funkcję dostępną na przykład na window. Jest to powiedzmy alert, to gdybym ja napisał
let alert, to tę funkcję, która tutaj jest dostępna
w ten sposób możemy window kropka albo zupełnie bez tego, bo jest to
globalne. Tylko byśmy ją przysłonili, ale byśmy jej nie nadpisali. Wiesz
już zatem jak korzystać z let i const. Jakie są ich zalety, a w kolejnej
lekcji jeszcze powiem ci kiedy korzystać z której z tych konstrukcji.