Zajęcia 1
1. Standard ECMAScript 6
W tej lekcji omówimy wybrane zagadnienia standardu ECMAScript 6. Otóż, jest to język skryptowy, którego jednym z dialektów jest znany nam już z kursu dla średniozaawansowanych JavaScript. Wtedy poznawaliśmy JavaScript w standardzie ECMAScript 5, który był bardzo popularny przez długi czas. Wraz z wejściem ES 6 w języku JavaScript pojawiły się nowe funkcjonalności. Część z nich omówimy dzisiaj. Poza tym omówimy kilka podstawowych zagadnień jeszcze z ES 5, o których nie było okazji powiedzieć wcześniej, a często o nie się pyta na rozmowach rekrutacyjnych na stanowiska związane z front-endem.
1.1. Closure
Zasięg stworzony przez funkcję, który rozgranicza zgromadzone w nim funkcje i zmienne od pozostałych części kodu tworząc dla nich osobne “środowisko” nazywamy domknięciem (z ang. closure).
Przykład 1.1.1.
var x = "Jestem globalny.";
function closure() {
var x = "Jestem w domknięciu.";
}
console.log(x);
Wywołanie ostatniej linii w powyższym przykładzie wyświetli w konsoli deweloperskiej “Jestem globalny.”. Funkcja closure() służy tutaj jako domknięcie, tzn. zmienna w funkcji i ta na zewnątrz to zupełnie dwie różne zmienne.
Jeśli byśmy jednak chcieli zmodyfikować zmienną z naszego przykładu wystarczy usunąć słowo kluczowe var w ciele funkcji.
Ćwiczenie 1.1.1.
Przeanalizuj działanie poniższego kodu źródłowego. Co zostanie wyświetlone w konsoli? Wyjaśnij działanie tego kodu.
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
Ćwiczenie 1.1.2.
Zaproponuj sposób naprawy kodu z ćwiczenia 1.1. tak, aby pętla faktycznie działała tak jak większość mogłaby się spodziewać. Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_112.js.
Podpowiedź - wykorzystaj funkcję natychmiastową.
1.2. Zasięg zmiennych
Jedną z najbardziej podstawowych nowości, które pojawiły się w standardzie ECMAScript 6 są nowe słowa kluczowe dotyczące deklaracji zmiennych.
W ES 5 mieliśmy tylko jeden zasięg zmiennych - zasięg funkcyjny, gdzie zmienne deklarowaliśmy ze słowem kluczowym var. Teraz pojawił się inny zasięg - zasięg blokowy, który będziemy deklarować słowem kluczowym let. Do tego dochodzi słowo kluczowe const, które oznacza deklarację stałej.
Co to znaczy zasięg blokowy zmiennych?
Do tej pory, aby umieścić zmienną w zakresie lokalnym musieliśmy używać domknięcia. Dzięki ECMAScript 6 nie ma potrzeby takiego “kombinowania”. Teraz możemy po prostu użyć zakresu blokowego.
Przykład 1.2.1.
/* Zasięg funkcyjny */
var i = 100; // zmienna globalna
for (var i = 0; i < 5; i++) { // nadpisanie tej samej zmiennej globalnej
// działanie pętli for
}
console.log(i); // wyświetli wartość 5
/* Domknięcie */
var j = 100;
(function () {
for (var j = 0; j < 5; j++) { // zmiennna lokalna
// działanie pętli for
}
})();
console.log(j); // wyświetli wartość 100
/* Zasięg blokowy */
let k = 100; // zmienna globalna
for (let k = 0; k < 5; k++) { // zmiennna lokalna w zakresie pętli for
// działanie pętli for
}
console.log(k); // wyświetli wartość 100
Ćwiczenie 1.2.1.
Kod napisany w ćwiczeniu 1.1.2. zmodyfikuj tak, aby wykorzystywał zakres lokalny zmiennych w ES6. Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_121.js.
No dobrze a co z tymi stałymi?
Stałych używamy, kiedy przypisanie wartości musi się odbywać wraz z deklaracją oraz gdy chcemy zabronić przypisywania nowej wartości do wcześniej utworzonej zmiennej.
Stałe nie przechowują obiektów ani tablic, a jedynie referencje do nich. I choć nie możemy przypisać stałym nowych referencji, to możemy zmienić same tablice czy obiekty bez wyrzucenia żadnego błędu. Dzieje się tak, gdyż referencje, a więc to, co przechowuje stała pozostają niezmienne.
Przykład 1.2.2.
const x = [1, 2, 3];
x = [2]; // wyświetli błąd
const y = {value: 7};
y = 6; // wyświetli błąd
/* Ale... */
const a = [1, 2, 3];
a[0] = 2; // to zadziała
const b = {value: 7};
b.value = 5; // to zadziała
b.newValue = 10; // to zadziała
1.3. Arrow functions
Przeanalizujmy treści dostępne na stronie blog.nebula.us/23-ecmascript-6-top-10-nowosci-cz-1-arrow-functions.
1.4. Hoisting
Przeanalizujmy treści dostępne na stronie http://poradnik.drogimex.pl/2017/05/20/hoisting-zmiennych-i-funkcji-w-javascript/.
1.5. Dziedziczenie - prototypy
Czasem w języku JavaScript będziemy chcieli rozwiązywać problemy tak jak robi się to w innych językach programowania. Jednak dziedziczenie w JS różni się od tego z obiektowych języków. Jak wiemy, język JavaScript nie posiada pojęcia klasy. Wszystko jest obiektem (a już na pewno funkcje). Każdy obiekt jest związany tzw. obiektem prototypu, np. każda funkcja, którą utworzymy dostaje od razu właściwość prototype, która zawiera nowy pusty obiekt. Właściwość ta zawiera w sobie właściwość constructor, która to z kolei wskazuje na utworzoną funkcję. Tak utworzony obiekt prototypu możemy wykorzystać do przypisywania do niego właściwości i funkcji - będą one współdzielone przez obiekty dziedziczące.
To co upodabnia dziedziczenie w JavaScript do języków programowania posiadających klasy jest słowo kluczowe new. Użycie tego słowa do wywołania funkcji zmienia jej zachowanie. Zamiast wywołać ją bezpośrednio, tworzony jest nowy obiekt, którego właściwość prototype jest wiązana z właściwością prototype tej funkcji. Ponadto słowo kluczowe this jest wiązane z nowo powstałym obiektem, więc wszystkie odwołania do this w tej funkcji odbywają się na rzecz nowo utworzonego obiektu (po wszystkich operacjach wszystkie instrukcje w funkcji również są wywoływane).
Przykład 1.5.1.
function Osoba(name){
this.name = name;
}
Osoba.prototype.getName = function (){
return this.name + ' Kowalski';
}
var test = new Osoba('Jan');
console.log(test.getName());
Przykład 1.5.2.
Wejdź na stronę Object-oriented JavaScript inheritance.
Ćwiczenie 1.5.1.
Napisz skrypt języka JavaScript, który tworzy “klasę” Figura z właściwością nazwa, a następnie “klasę” Czworokat, która dziedziczy z Figura. Jej właściwości to typ-czworokata oraz dlugosci-bokow. Dalej utwórz “klasę” Prostokat, która dziedziczy z “klasy” Czworokat. Posiada ona metodę podaj-pole i podaj-obwod. Utwórz obiekt “klasy” Prostokąt, ustaw mu wymiary 5x8 i wypisz jego nazwę, typ, pole oraz obwód.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_151.js.
Jak to robić łatwiej i bardziej “obiektowo” w ES6?
Używając słów class oraz extends.
Przykład 1.5.3.
class Animal {
constructor(name) {
this.name = name;
}
talk() {
console.log(this.name + ' talks.');
}
}
class Dog extends Animal {
talk() {
super.talk();
console.log(this.name + ' barks.');
}
}
let animal = new Animal('Mruczek');
animal.talk();
let dog = new Dog('Puszek');
dog.talk();
console.log(typeof animal === typeof dog);
console.log(typeof dog);
Mimo, że używamy tutaj słów znanych z innych języków programowania to tak na prawdę “pod spodem” dalej mamy prototypy :)
Ćwiczenie 1.5.2.
Zmodyfikuj rozwiązanie ćwiczenia 1.5.1. tak, aby używać słów class oraz extends.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_152.js.
1.6. Skróty składniowe i destructuring
Przeczytaj materiały dostępne na stronie blog.nebula.us/31-ecmascript-6-top-10-nowosci-cz-9-skroty-skladniowe-i-destructuring. Treści tam zawarte zostaną poruszone w zadaniu domowym nr 3.
1.7. Domyślne parametry funkcji
Przeczytaj materiały dostępne na stronie blog.nebula.us/29-ecmascript-6-top-10-nowosci-cz-7-domyslne-parametry-funkcji a następnie wykonaj poniższe ćwiczenie. Treści zawarte na tej stronie zostaną poruszone w zadaniu domowym nr 3.
Ćwiczenie 1.7.1.
Napisz funkcję języka JavaScript, która dla podanego jako argument kąta (w stopniach), promienia oraz wartości liczby PI wyznaczy pole wycinka koła. Parametrem domyślnym jest trzeci argument czyli wartość liczby PI (domyślna wartość PI=Math.PI). Następnie wywołaj tę funkcję z następującymi argumentami:
- (30, 5, 3.14);
- (30, 5, 22/7);
- (30, 5).
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_171.js.
1.8. Nowe możliwości stringów
Przeczytaj materiały dostępne na stronie blog.nebula.us/26-ecmascript-6-top-10-nowosci-cz-4-nowe-mozliwosci-stringow a następnie wykonaj poniższe ćwiczenie. Treści zawarte na tej stronie zostaną poruszone w zadaniu domowym nr 3.
Ćwiczenie 1.8.1.
Dany jest kod źródłowy języka JavaScript:
var s = 'Podstawą szczęścia jest wolność, a podstawą wolności odwaga.';
var text = 'Operuję na zdaniu: "Podstawą szczęścia jest wolność, a podstawą wolności odwaga." <br /><br />' + 'Trzynastym znakiem w tym zdaniu jest: ' + s.charAt(13) + '. <br />' + 'Znaki pomiędzy 7. a 12. pozycją to: ' + s.substring(7, 12) + '. <br />' + "Pierwszy raz znak 'ą' pojawia się na miejscu: " + s.indexOf('ą') + '. <br />' + 'Ten ciąg ma ' + s.length + ' znaków. <br/>' + "Po zamianie 'podstawą' na 'fundamentem' mamy: " + s.replace('podstawą', 'fundamentem') + '. <br />' + 'Część zdania przed przecinkiem to: ' + s.split(',')[0] + '. <br />' + 'Druga część zdania po odwróceniu to: ' + s.split(',')[1].split('').reverse().join('') + '.'
console.log(text);
Popraw ten kod tak, aby w drugiej zmiennej nie były wykorzystywane znaki dodawania. Ciąg znaków do niej przypisany nie powinien być wyświetlany w jednej linii tylko tak, aby całość była widoczna na szerokości ekranu Twojego edytora kodów źródłowych.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij exercise_181.js.
1.9. Callbacki i obiekt Promise
Przeczytaj materiały dostępne na stronie blog.nebula.us/27-ecmascript-6-top-10-nowosci-cz-5-promises. Treści tam zawarte zostaną poruszone w zadaniu domowym nr 3.
Zadania domowe
Zadanie 0.
Rozwiąż quiz dostepny na classmarker.com o nazwie ECMAScript 6 - cz. I.
Zadanie 1.
Napisz skrypt języka JavaScript, który utworzy “klasę” Osoba z właściwościami imie, nazwisko, rokUrodzenia, plec oraz metodą podajWiek, która korzystając z obiektu Date oblicza wiek danej osoby.
Utwórz też “klasę” Nauczyciel, która również będzie dziedziczyć z klasy Osoba i będzie zawierać pole nauczanyPrzedmiot i rokRozpoczeciaPracy. Do tego metoda podajIloscLatPracy, która działa analogicznie do metody podajWiek.
Utwórz “klasę” Wychowawca, która dziedziczy z klasy Nauczyciel i będzie zawierać pole przydzielonaKlasa.
Utwórz obiekt klasy Wychowawca z danym imieniem, nazwiskiem, rokiem urodzenia, płcią, nauczanym przedmiotem oraz rokiem rozpoczęcia pracy. Wywołaj na nim metody podajWiek i podajIloscLatPracy.
Wyświetl w konsoli deweloperskiej cały obiekt i to, co zwróciły metody.
Zadanie wykonaj na 2 sposoby, które poznaliśmy na zajęciach - bez użycia słów class (w nazwie pliku z rozwiązaniem dajemy literę A) oraz extends a następnie z użyciem tych słów (w nazwie pliku z rozwiązaniem dajemy literę B).
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_01. Skrypt z rozwiązaniem nazwij homework_task_01A.js i homework_task_01B.js.
Zadanie 2.
Przeczytaj zawartość punktów 1.6.-1.9. w tej lekcji i zrób wszystkie ćwiczenia, które tam się znajdują. Rozwiązania ćwiczeń umieść na repozytorium Githuba.
Zadanie 3.
Rozwiąż quiz dostepny na classmarker.com o nazwie ECMAScript 6 - cz. II.
Źródła
- Duckett Jon, JavaScript and JQuery: Interactive Front-End Web Development, przeł. Robert Górczyński, Helion, 2015, ISBN 978-83-283-0126-9.
- blog.nebula.us/13-javascript-closures-czyli-zrozumiec-i-wykorzystac-domkniecia
- blog.nebula.us/25-ecmascript-6-top-10-nowosci-cz-3-let-czyli-blokowy-zakres-zmiennych
- nafrontendzie.pl/dziedziczenie-javascript-wersja-klasyczna
- blog.nebula.us/23-ecmascript-6-top-10-nowosci-cz-1-arrow-functions
- blog.nebula.us/26-ecmascript-6-top-10-nowosci-cz-4-nowe-mozliwosci-stringow
- blog.nebula.us/29-ecmascript-6-top-10-nowosci-cz-7-domyslne-parametry-funkcji
- blog.nebula.us/31-ecmascript-6-top-10-nowosci-cz-9-skroty-skladniowe-i-destructuring
- blog.nebula.us/27-ecmascript-6-top-10-nowosci-cz-5-promises
- poradnik.drogimex.pl/2017/05/20/hoisting-zmiennych-i-funkcji-w-javascript