Download as pdf or txt
Download as pdf or txt
You are on page 1of 79

INŻYNIERIA INTERNETU

WYKŁADY INFORMATYKA TECHNICZNA


2023/2024

JAVASCRIPT I TYPESCRIPT

Krzysztof Bzowski <kbzowski@agh.edu.pl>


CO MA JAVA DO JAVASCRIPT?
• NIC – To całkowicie różne języki
• Początkiem lat 90 Sun Microsystems stworzyło język Java (nazwa pochodzi od kawy
produkowanej na wyspie Jawa), którego ideą był WORA - Write once, run anywhere.
• Netscape Communications chciało wprowadzić do swojej przeglądarki dynamikę
znaną z programów desktopowych. Sun Microsystems chciało aby Netscape
Communications wprowadziło do swojej przeglądarki Javę. Netscape
Communications odmówiło.

• W 1995 Brendan Eich z Netscape Communications tworzy LiveScript – dynamiczny język dla przeglądarek www. Nowość
nie przyjęła się za dobrze – zainteresowanie programistów było nikłe.
• Koniec 1995 – Z pobudek czysto marketingowych, przemianowano LiveScript na JavaScript (za zgodą i licencją Sun)
• Wiele implementacji (1996 - 2006 Microsoft rozwijał swój JScript)
• 1997 - Netscape Communications wraz z ECMA tworzy standard nowego języka – ECMAScript pod patronatem ECMA
(European Computer Manufacturers Association) .
• Stabilny rozwój ES1-3 (do 1999r), problemy z ES4 (rozwój wstrzymany na blisko 10 lat), drobne zmiany ES5 (2011r).
Współczesny JS == ES6 (2015)
JAVASCRIPT W 2023
• To co nazywamy dziś JavaScript to implementacja języka ECMAScript (w skrócie ES)
• Standard jest cały czas uaktualniany. Od roku 2015 (ES6 == ES2015), powstaje nowa
wersja, którą zajmuje się komisja TC39 (Technical Committee)
• Każdy nowy element języka przechodzi 5 poziomów:
• 🤷🏻 Stage 0: Strawperson - pomysły
• 💡 Stage 1: Proposal – Formalny opis pomysłu, API, przykłady, dyskusja
• ✍🏻 Stage 2: Draft – Wstępny szkic specyfikacji, składni, wstępna implementacja i testy
• 📝 Stage 3: Candidate – Ostatnie szlify, recenzje, gotowa implementacja, nie powinno być żadnych
otwartych tematów
• ✅ Stage 4: Finished – propozycja trafia do specyfikacji standardu

• Przykład: https://github.com/tc39/proposal-pipeline-operator
• Obecna wersja standardu: ES2023 (lub ES14) (czerwiec 2023) -
https://tc39.es/ecma262/2023/

Uwaga: przyjęcie standardu nie oznacza, że każde środowisko implementujące JavaScript


będzie z nim zgodne od tego dnia! - https://node.green/ , https://caniuse.com
CIEKAWOSTKA https://babeljs.io/

• Jak zapoznać się z elementami języka


spoza obecnego standardu?
• Babel – transpiler JavaScript, którego celem
jest przekształcenie kodu z jednego standardu
w drugi, oparty o system wtyczek (plugin).
• Transformacje kodu: Pozwala wzbogacać język
o dodatkowe funkcjonalności (np. react-jsx)
• Polyfiling: Babel może dodawać tzw. "polyfills"
do kodu, aby umożliwić korzystanie z
nowszych funkcji i obiektów JavaScript w
starszych środowiskach. Polyfill to fragment
kodu, który dostarcza funkcjonalności, której
brakuje w danym środowisku.
IMPLEMENTACJE JS
• W przeglądarkach:
• V8 – Google Chrome, Edge, Opera
• SpiderMonkey – Firefox
• JavaScriptCore - Safari
• Implementacje serwerowe:
• NodeJS – na serwerach (oparte na V8)
• Deno – na serwerach ze wsparciem TS (oparte na V8)
• Bun – nowy eksperymentalny (oparty o silnik JavaScriptCore)
• W każdym przypadku mamy tą samą składnię kodu JavaScript, API jest
jednak inne – inne potrzeby w przeglądarkach (np. manipulacje DOM), inne
w skryptach serwera (np. obsługa plików)
CO TRZEBA WIEDZIEĆ O NODEJS I JS
• Jest (zwykle) jednowątkowy i asynchroniczny - Jego architektura oparta jest na
zdarzeniach i nieblokujących operacjach wejścia/wyjścia, które pozwalają
na maksymalizację wykorzystania pojedynczego procesora i pamięci
komputera, dzięki czemu serwery są szybsze i bardziej wydajne.
• Stosunkowo lekki, skalowalny
• Wieloparadygmatowy: jest językiem funkcjonalnym z elementami OOP
• Mnóstwo dodatkowych bibliotek łatwo instalowanych przez npm:
https://www.npmjs.com/
• Dobrze łączy się z natywnym kodem w C++ - Node-API
• Wysoka popularność (społeczność)
• Nie nadaje się do operacji silnie wykorzystujących CPU (ale rozwiązujemy to
kodem natywnym lub WebAssembly)
• Pisząc UI do przeglądarki i tak nie masz wyboru (TypeScript, ClojureScript,
CoffeeScript kompilują do JS)
JAK DZIAŁA JS
• Wersja bardzo... bardzo uproszczona:
• JavaScript wykonuje kod linia po linii
(jednowątkowo). Ale niektóre rzeczy, jak czekanie
na kliknięcie przycisku lub na odpowiedź z
internetu, mogą trwać długo. Pętla zdarzeń pomaga
JavaScriptowi robić inne rzeczy, podczas gdy czeka
na te "wolne" zadania.
1. Stos wywołań (call stack) - To miejsce, gdzie Interpreter
JavaScript "umieszcza" funkcje, które ma właśnie
wykonać.
2. Kolejka zdarzeń (task queue) - kiedy coś trwa długo (np.
kliknięcie przycisku), zadanie trafia do kolejki zdarzeń.
3. Pętla zdarzeń (event loop) - jeśli stos wywołań jest pusty
(JavaScript nie ma nic do roboty), pętla zdarzeń przenosi
zadanie z listy kolejki na stos wywołań
Bibliografia:
Philip Roberrs - What the heck is the event loop anyway, JSConf EU, 2014 (są polskie napisy)
INTERPRETERY W PRAKTYCE
• Każda przeglądarka www posiada wbudowany interpreter JavaScript
(zwykle dostępny w narzędziach programisty – F12)
• NodeJS można uruchomić w wierszu poleceń (cmd, power shell, bash)
OSADZANIE JS W KODZIE HTML
JS PODSTAWY – DEKLAROWANIE ZMIENNYCH
TYPY W JAVASCRIPT
• W JS nie podajemy wprost typów zmiennych – są one dedukowane z przypisanych wartości. Prymitywy w JS:
• Boolean – typy logiczne
• Null – wartość „pusta”
• Undefined – brak przypisanej wartości (jeśli nie zainicjalizujemy zmiennej)

let a; // jest undefined, bo nie ma przypisanej wartości


let b = null; // ma przypisaną wartość null

• Number – liczby (zarówno stało jak i zmiennoprzecinkowe)


• BigInt – wartości większe niż 253
const c = 9007199254740991n;
const d = BigInt(9007199254740991);

• String - napis
• Symbol – unikalna wartość (stosowana np. jako klucz w obiektach)
• Prymitywy są niezmienne (immutable)
• Wszystko co nie jest prymitywem dziedziczy po obiekcie:
• Tablice
• Funkcje
• Instancje klas
• Obiekty
SPRAWDZENIE TYPU - TYPEOF
• Typ prymitywu można sprawdzić podczas działania skryptu (runtime)
za pomocą operatora typeof zwracającego typ jako string
JS PODSTAWY – VAR
• var to przestarzały sposób deklaracji zmiennych
• Odradza się używać deklaracji zmiennych z wykorzystaniem var
Zasięg Funkcji: Hoisting

Ponowna deklaracja:

W kodach zaliczeniowych ZAKAZ używania var


JS PODSTAWY – KONSOLA
JS PODSTAWY – KONSOLA
JS PODSTAWY – WARUNKI
OPERATOR WARUNKOWY

Kiedy warunek == true Kiedy warunek == false


SWITCH/CASE
JS PODSTAWY – MATEMATYKA
TRY/CATCH

Ten kod nie ma sensu – ma pokazać jak się rzuca wyjątki


JS PODSTAWY – TABLICE
JS PODSTAWY – FOR… OF VS FOR… IN
JS PODSTAWY – TABLICE

index Ilość elementów


JS PODSTAWY - FUNKCJE
nazwa funkcji Argumenty (dowolna ilość, po przecinku)

Wartość
zwracana (lub jej
brak)
JS PODSTAWY – ARROW FUNCTIONS
FUNKCJE JAKO OBIEKTY PIERWSZEJ KLASY
W językach programowania, w których funkcje są traktowane jako
"obiekty pierwszej klasy" (first-class citizens), funkcje mogą być:
Przekazywane jako argumenty do innych funkcji:

Zwracane jako wartości z innych funkcji:

Przypisywane do zmiennych:
FUNKCJE ANONIMOWE I WYŻSZEGO RZĘDU
• Funkcje anonimowe najczęściej stosujemy jako argumenty innych
funkcji (tzw. callback)
JS PODSTAWY – FUNKCJE
CLOSURES (DOMKNIĘCIA)

Funkcja wewnątrz innej funkcji ma zawsze dostęp do


stanu funkcji nadrzędnej
JS PODSTAWY – FUNKCJE
Z definicji w JS prymityw jest zawsze przekazywany do funkcji przez
wartość, a nie-prymityw przez referencje (czyli adres w pamięci)
JS PODSTAWY – FUNKCJE TABLIC
every zwraca true jeśli wszystkie elementy spełniają test

some zwraca true jeśli choć jeden element spełnia test


JS PODSTAWY – FUNKCJE TABLIC
map zwraca nową tablicę na podstawie istniejącej gdzie każdy element zmodyfikowany jest wg przepisu

filter zwraca nową tablicę z elementami które przechodzą dany test


FUNKCJE TABLIC
find – zwraca referencję do pierwszego elementu spełniającego dany test
findIndex – zwraca index elementu spełanijącego dany test

Literatura uzupełniająca: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array


OBIEKTOWOŚĆ
Obiekt w JS NIE MUSI być instancją klasy
OBIEKTOWOŚĆ
THIS W OBIEKCIE

Funkcje strzałkowe nie


mają wiązania this w
obiekcie!
OBIEKTOWOŚĆ - KLASY
Konstruktor Funkcje strzałkowe nie
może być konstruktorem

Funkcje strzałkowe ma
dostęp w klasie do jej
Gettery i settery składników

Do tworzenia instancji
klas używamy new
OBIEKTOWOŚĆ
KOPIOWANIE OBIEKTÓW
KOPIOWANIE GŁĘBOKIE
• Object.assign: Używana do kopiowania wartości wszystkich wyliczalnych własnych właściwości z
jednego lub więcej obiektów źródłowych do obiektu docelowego. Jest to płytkie kopiowanie, co
oznacza, że dla zagnieżdżonych obiektów kopiowane są tylko referencje, a nie faktyczne obiekty.
• structuredClone: Umożliwia głębokie kopiowanie obiektów. Wprowadzone w ES2022. Kopiuje
zarówno prymitywne wartości, jak i struktury zagnieżdżone, utrzymując ich strukturę i zawartość.
UŻYTECZNE FUNKCJE JĘZYKA
• Wyłuskania (spread)
UŻYTECZNE FUNKCJE JĘZYKA
• Wyłuskanie
UŻYTECZNE OPERATORY
• Rest - Zapis ten umożliwia zbieranie w jedną zmienną (będącą tablicą)
wielu parametrów przekazywanych do funkcji

• Przydaje się w przypadku przekazania (bez ich znajomości) wszystkich


parametrów funkcji do innej funkcji
UŻYTECZNE FUNKCJE JĘZYKA
• Nullish coalescing

Typu nullish – to typy nullo podobne (undefined i null). Uwaga: false nie jest nullish!

OR (||), zwraca prawą stronę


wyrażenia, gdy lewa strona jest
fałszywa (falsy), co obejmuje wartości
takie jak 0, "" (pusty łańcuch), NaN,
false, null, i undefined
UŻYTECZNE FUNKCJE JĘZYKA
• Shorthand property names (skrócone nazwy właściwości)
UŻYTECZNE FUNKCJE JĘZYKA
• Optional chaining
UŻYTECZNE FUNKCJE JĘZYKA
• Logical nullish assignment – przypisz wartość jeśli z lewej strony jest
null lub undefined (nullish)
JSDOC – DOKUMENTACJA KODU

Webstorm
(po najechaniu kursorem na kod
posiadający dokumentacje)
TYPESCRIPT
• Semantyczny nadzbiór języka JavaScript.
• Każdy poprawny kod JS będzie kompatybilny z TS
• Kod TS nie jest kompatybilny z JS (inna składnia)
• Aby uruchomić kod TS w Node (lub przeglądarce) konieczna jest transpilacja
do JS
• Motywacja: statyczna kontrola typów (na etapie
implementacji/transpilacji)
TYPESCRIPT
• TypeScript jest kompilowalny (transpilowalny) do JavaScript. Typy z kodu wynikowego są
usuwane
• Wynikowy JavaScript można uruchomić w przeglądarce lub NodeJS
JavaScript
TypeScript
TYPESCRIPT
• Typy:
• string
• number
• boolean
• tablice (np. number[])
• tuples (np. [number, string])
• any
• unie (number | string) konkretny typ można sprawdzić operatorem typeof
• null i undefined
• Enum
• BigInt (liczby do 253-1)
• Wnioskowanie typów: const liczba = 4;
https://www.typescriptlang.org/docs/handbook/2/everyday-types.html
TYPESCRIPT
• Typ • Interfejs

• Zarówno typ jak i interfejs służą do opisu „kształtu danych”, ale nie
zawierają ŻADNEJ funkcjonalności. W większości przypadków można
je używać wymiennie.
• Typ jest aliasem dla innych typów lub zbiorów typów
• Interfejsy to umowa określająca wymagania, które musi spełniać obiekt.
• Obie informacje są tracone przy transpilacji do JS (w przeciwieństwie do klas)
KONTROLA TYPÓW W TYPESCRIPT
TypeScript wprowadza statyczną kontrolę typów. To oznacza, że zanim kod zostanie
skompilowany do czystego JavaScript, TypeScript sprawdza, czy wszystkie zmienne, funkcje itp.
są używane zgodnie z zadeklarowanymi typami.

TypeScript ocenia, czy


struktura joe jest zgodna z
Każdy obiekt typu TypeScript będzie teraz wymagać, aby interfejsem Person.
Chociaż obiekt joe ma
Person musi zawierać każdy argument przekazany do funkcji Chociaż joe ma dodatkową
dodatkową właściwość job,
właściwość name, która greet miał strukturę zgodną z właściwość job, TypeScript
której nie ma w interfejsie
jest typu string, oraz interfejsem Person. nie zgłasza błędu,
Person, obiekt joe spełnia
właściwość age, która ponieważ system typów
jednak wszystkie wymagania
jest typu number. TypeScript jest
interfejsu Person (ma
strukturalny, a nie
właściwości name i age o
nominalny. Oznacza to, że
odpowiednich typach).
TypeScript ocenia typy na
podstawie ich struktury, a
nie nazw.
TYPESCRIPT – TYP CZY INTERFEJS
• Interfejsy można redeklarować powodując ich łączenie, typy nie

• Interfejsy i typy można rozszerzać


TYPESCRIPT – TYP CZY INTERFEJS
• Typy mogą służyć za aliasy (interfejsy nie)

• Interfejsy mogą być rozszerzane przez inne interfejsy, a klasy mogą


implementować interfejsy (typy nie)
TYPESCRIPT – TYP CZY INTERFEJS
• Typy mogą tworzyć unie prymitywów i innych typów/interfejsów,
interfejsy nie mogą tworzyć unii.
TYPESCRIPT – TYP CZY INTERFEJS
• Klasy mogą rozszerzać interfejsy, typy - nie.

• Interfejsy lepiej radzą sobie z obsługą błędów w wyniku duplikatów pól


TYPESCRIPT – TYP CZY INTERFEJS
• Wybór sposobu opisu kształtu danych (typ/interfejs) zależy głównie od
indywidualnych preferencji, czytelności i kontekstu kodu.
• W dużych projektach Interfejsy mogą okazać się szybsze (w rozumieniu
czasu transpilacji)
• Interfejs czy typ?
• Jeśli potrzebujemy grupowania lub kontraktu dla klas: użyj interfejsu
• Jeśli potrzebujesz nowego typu lub aliasu typu istniejącego: użyj typu
• Jeśli nie wiesz czego potrzebujesz: użyj interfejsu (będzie bezpieczniej!)
DEKLARACJE WŁAŚCIWOŚCI TYPÓW I INTERFEJSÓW
Pole opcjonalne, nie musi być obecne, typ pola z
'?' to zawsze unia typ|undefined, tu:
number|undefined
Pole wymagane, które musi być obecne w obiekcie
MODUŁY
W TypeScript, moduł to sposób organizowania kodu w mniejsze, zarządzalne fragmenty. Moduły pozwalają na
izolowanie logiki, enkapsulację, reużywalność kodu i zarządzanie zależnościami. Moduł == plik
Każda funkcja/klasa/zmienna jest widoczna tylko w
MODUŁY określonym module (pliku .ts).

Ze względu na tzw „tree-shaking” zalecanie jest używać eksportów


nazwanych
IMPORT BIBLIOTEK

Import z "lokalnego" pliku animals.ts

Import z pakietu animals


(zainstalowanego w "node_modules"
przez npm)
GENERYCZNOŚĆ

Podpowiedź: Istnieje metoda reverse w tablicy!


GENERYCZNOŚĆ W KLASACH
UNIE
UNIE
NARROWING

• Warto przeczytać: https://www.typescriptlang.org/docs/handbook/2/narrowing.html


TYPY POMOCNICZE (UTILITY TYPES)
• Utility Types to zestaw typów pomocniczych, które pozwalają na
transformację jednego typu w drugi
• Partial<T> - Tworzy typ, który zawiera wszystkie właściwości danego typu,
ale wszystkie te właściwości są opcjonalne.

Literatura uzupełniająca: https://www.typescriptlang.org/docs/handbook/utility-types.html


TYPY POMOCNICZE (UTILITY TYPES)
• Record<Keys, Type> - Tworzy obiekt typu, którego klucze są Keys, a
wartości są Type.

• Pick<Type, Keys> - Tworzy typ z wybranych kluczy (Keys) z danego typu.


TYPY POMOCNICZE (UTILITY TYPES)
• Omit<Keys, Type> - Tworzy typ poprzez pominięcie wybranych kluczy
(Keys) z danego typu.

• ReturnType - pozwala na wywnioskowanie (ekstrakcję) typu zwracanego


przez funkcję.
TYP FUNKCYJNY (FUNCTION TYPES)
PRZEŁADOWANIE NAZW FUNKCJI
Pozwala na definiowanie wielu sygnatur dla jednej funkcji. W JavaScript, jeśli
zdefiniujesz dwie funkcje o tej samej nazwie, druga definicja nadpisze pierwszą.
1. Definiujesz sygnatury funkcji

2. Dostarczasz implementację 3. Wywołaj funkcję


OPERATOR KEYOF
Pozwala uzyskać typ
reprezentujący
zestaw kluczy (lub
właściwości) obiektu
MATERIAŁY UZUPEŁNIAJĄCE
• Dokumentacja TypeScript – lektura obowiązkowa:
https://www.typescriptlang.org/docs/handbook/
• TypeScript Notes for Professionals:
https://goalkicker.com/TypeScriptBook2/TypeScriptNotesForProfessionals.pdf
• Stefan Baumgartner: TypeScript in 50 Lessons
INSTALACJA TYPESCRIPT
• Dodanie wsparcia do TS do projektu JS
npm i -D typescript ts-node
lub
yarn add --dev typescript ts-node
• Utworzenie konfiguracji transpilatora (transkompilator)
.\node_modules\.bin\tsc --init
• Zmień konfigurację tsconfig.json
"outDir": "./dist", - Katalog wynikowy (z plikami JS)
"sourceMap": true, - Wymagane aby można debugować kod
• Stwórz plik index.ts i uzupełnij go kodem
• Uruchom .\node_modules\.bin\tsc lub
.\node_modules\.bin\tsc -w
URUCHAMIANIE W WEBSTORM (OPCJA 1)
• Uruchomienie skryptu TypeScript: Run -> Edit Configuration
URUCHAMIANIE W WEBSTORM (OPCJA 2)
• Uruchomienie skryptu TypeScript: Run -> Edit Configuration
AUTOMATYCZNA TRANSPILACJA (NIEZALEŻNE OD IDE)
• Uruchomienie skryptu TypeScript (OPCJA 3) – automatyczna
przebudowa przy zmianie zawartości
(tryb watch)
• Do package.json w sekcji scripts dodać:

• Uruchomić skrypt w konsoli:


npm run watch
• Każda zmiana w pliku ts automatycznie
skompiluje go do js dopóki skrypt watch
będzie działać w tle
URUCHOMIENIE BEZPOŚREDNIE
• Możliwe jest uruchomienie skryptu ts bezpośrednio z linii komend bez
wstępnej tanspilacji: ts-node nazwa_pliku.ts

You might also like