JS cz.4
TRY CATCH
Opcjonalny blok: Try catch – konstrukcja, która sprawdza czy daną funkcję da się wykonać, jeżeli da się – wykonuje, jeśli nie – wywołuje obiekt Error, errora,to pełnoprawny blok kodu – ale nie powinno owijać nim całego programu, będzie wtedy maskować błędu – trzeba go używać w przypadkach kiedy mamy nieufność do użytkownika, ładowanie plików, styczność „ze światem zewnętrznym” – wtedy kiedy może się coś wysypać
Instrukcja try–catch (w językach takich jak Java, C#, JavaScript, Python – choć tam jest try–except) służy do obsługi wyjątków, czyli błędów, które mogą pojawić się podczas wykonywania programu.
try{
const obiekt = null;
console.log(obiekt.wlasciwosc); // To wywoła TypeError
} catch (error) {
console.error("Wystąpił błąd:", error.message);
}
console.log("Program kontynuuje działanie po obsłudze błędu.");
PO try catch kolejne linijki kodu będą dalej czytane!!!
Ten obiekt ma właściwości – otrzymujemy je w kluczu massage
To obsługuje potencjalne błędy (3 rodzaje kategorii błędów – złe dane od użytkownika, niewykonanie operacji – bo nie było zasobów, nie istnieją zasoby – była awaria i nie ma pliku). Łapiemy te błędy, które umiemy obsłużyć.
WAŻNE w JS dzielenie przez 0 wywołuje NaN a nie Error – try catch na dzieleniu przez 0 nie zadziała
- Blok try
W tym bloku umieszczasz kod, który może potencjalnie spowodować błąd. - Blok catch
Jeśli w bloku try wystąpi wyjątek, program przeskoczy do bloku catch i wykona znajdujący się tam kod zamiast przerwać działanie. - (Opcjonalnie) blok finally
Kod w finally wykona się zawsze, niezależnie od tego, czy pojawił się błąd, czy nie — zwykle używany do sprzątania zasobów (np. zamykanie plików).
Po co się tego używa?
• żeby nie wywalać programu przy błędach
• żeby elegancko obsługiwać sytuacje problemowe (np. brak pliku, błąd połączenia)
• żeby przechwytywać różne typy błędów (różne catch)
Try…catch łapie:
• wszystkie standardowe błędy JS (TypeError, ReferenceError, itd.)
• Twoje własne błędy (throw new Error())
• dowolne wartości, które „rzucisz” (throw 123)
• błędy w async/await, jeśli użyjesz go z try…catch
• błędy składni tylko wewnątrz eval
Try…catch NIE łapie:
• błędów składni kodu ładowanego normalnie
• błędów asynchronicznych poza blokiem catch
Syntax error – błąd składni – zwykle vs code podreśli lub wyświetli przy uruchamianiu programu
Range error – np. za głęboka rekurencja, wyjście poza zakres danych
THIS
this – słowo kluczowe dla JS ale mylące, to wartość (dopisywana do zmiennej) określona przez sposób wywołania funkcji, to referencja do kontekstu funkcji, który może się zmienić (bo funkcja może być wywołana np. jako konstruktor)
Jest 5 głównych kontekstów, są określone wartości wywoływane przez this dla każdej z nich
Globalny - wywołuje: obiekt window, który opisuje okno przeglądarki
Funkcji – jeśli wołam this w funkcji i nie mam innego kontekstu, żadnej wartości, argumentu – to również otrzymam window
*jeśli mam tryb dla funkcji ustawiony na ‘use strict” – dostanę undefined
*jeśli wołamy w funkcji zagnieżdżonej, wewnętrznej – dostanę window (bo nie mam argumentu, więc będzie odwołanie globalne)
*jeśli przekazujemy funkcję do funkcji – globalnie window, ale this zmieni się na: pokaż this
Metody -metodę wywołuje z zewnątrz obiektu, this- wskaże obiekt / tu jakiś problem 17:51
Konstruktora - wywołuje nowoutworzony obiekt
Funkcja strzałkowa - dzidziczy this z otoczenia
| Kontekst | this wskazuje na… |
|---|---|
| Globalny | obiekt globalny (window/global) |
| Zwykła funkcja | obiekt wywołujący / undefined w strict |
| Metoda obiektu | obiekt, który wywołał metodę |
| Konstruktor / klasy | nowo utworzony obiekt |
| Funkcja strzałkowa | dziedziczy this z otoczenia |
this w event handlerze (event handler (ang. „obsługiwacz zdarzeń”) to funkcja, która zostaje wywołana, gdy wystąpi określone zdarzenie, np. kliknięcie myszką, wpisanie tekstu, scrollowanie strony.)
Jeśli używasz zwykłej funkcji (function(event) {}), this wskazuje na element, który wywołał zdarzenie (np. przycisk).
this nie ma specjalnej składni – jest to po prostu słowo kluczowe w JavaScript, które automatycznie wskazuje na kontekst wywołania funkcji.
const obj = {
name: "Ala",
sayName() {
console.log(this.name);
}
};
obj.sayName(); // Alathis pozwala funkcji lub metodzie wiedzieć, „kto ją wywołał” – czyli działa w zależności od kontekstu. Bez tego trudno byłoby pisać uniwersalne funkcje i metody, które działają na różnych obiektach.
const person = {
name: "Ala",
greet() {
console.log("Cześć, mam na imię " + this.name);
}
};
person.greet(); // Cześć, mam na imię Alathis.namepozwala metodziegreetwiedzieć, do którego obiektu należy.- Dzięki temu możesz mieć wiele obiektów z tą samą metodą, a metoda zawsze użyje właściwego
name.
Chaining metod, gettery i settery – łączą się z this, bo wszystkie działają w kontekście obiektu, na którym są wywoływane:
Chaining metod (łańcuchowanie metod)
Chaining polega na wywoływaniu wielu metod jedna po drugiej na tym samym obiekcie, dzięki temu, że metoda zwraca this.
const obj = {
value: 0,
add(x) {
this.value += x;
return this; // zwracamy obiekt, żeby móc łańcuchować
},
multiply(x) {
this.value *= x;
return this;
}
};
obj.add(2).multiply(3); // chaining
console.log(obj.value); // 6Dlaczego this jest ważne?
- Metoda zwraca
this, czyli ten sam obiekt, więc możesz dalej wywoływać kolejne metody na nim.
Gettery (get)
- Getter pozwala pobierać właściwość obiektu tak, jakby to była zwykła zmienna, ale pod spodem może wykonywać logikę.
thisw getterze wskazuje na obiekt, którego właściwość pobierasz.
const person = {
firstName: "Ala",
lastName: "Nowak",
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
};
console.log(person.fullName); // Ala Nowaktu his.firstName i this.lastName odnoszą się do obiektu person.
Settery (set)
- Setter pozwala ustawiać właściwość obiektu, ale możesz przy tym wykonać dodatkową logikę.
thisw setterze również wskazuje na obiekt, którego właściwość ustawiasz.
Settery (set)
Setter pozwala ustawiać właściwość obiektu, ale możesz przy tym wykonać dodatkową logikę.
this w setterze również wskazuje na obiekt, którego właściwość ustawiasz.PODSUMOWANIE:
Chaining metod → this pozwala zwracać obiekt i wywoływać kolejne metody.
Getter → this pozwala pobierać dane z obiektu, w którym jesteśmy.
Setter → this pozwala modyfikować dane w tym samym obiekcie.
METHOD SHORTHAND (ES6)
W kontekście JavaScript, termin “shorthand” odnosi się do skróconego zapisu kodu, który pozwala pisać te same rzeczy w bardziej zwięzły sposób. Chodzi głównie o skróty składniowe w deklaracjach, przypisaniach i funkcjach
const o = { x() {} }
const o = {
x: function() {
console.log("Hello");
}
};const o = {
x() {
console.log("Hello");
}
};TABLICE
- sposób literał – wypisanie wartości krok po kroku
-w jednej tablicy możemy trzymać różne typy elementów / tzw. mieszana
const arr = [1, 2, 3];
- konstruktor / new Array () – to jest pusta tablica z konstruktora
const arr = new Array(3); // pusta tablica o długości 3
const arr2 = new Array(1, 2, 3); // tablica z elementami
- tworzenie tablicy z podanych elementów
const arr = Array.of(1, 2, 3); // [1, 2, 3]
- tworzenie tablicy z iterowane obiektu
const str = "abc";
const arr = Array.from(str); // ["a", "b", "c"]
1 tworzenie tablicy o określonym rozmiarze
const rozmiarTablicy = new Array(5); // tablica z 5 pustymi miejscami
console.log("Tablica o rozmiarze 5:", rozmiarTablicy);
console.log("Długość tablicy:", rozmiarTablicy.length);
const tablicaJedenEl = new Array("5");
console.log("Tablica z jednym elementem '5':", tablicaJedenEl);METOY TABLICOWE
W JavaScript metody tablicowe to funkcje, które pozwalają łatwo operować na tablicach: przeglądać, zmieniać, filtrować, mapować i łączyć elementy
|
Metoda |
Co robi? |
Gdzie? |
Co zwraca? |
|
push() |
dodaje |
na koniec |
nową długość |
|
pop() |
usuwa |
z końca |
usunięty element |
|
shift() |
usuwa |
z początku |
usunięty element |
|
unshift() |
dodaje |
na początku |
nową długość |
// 1. PUSH - dodaj na koniec
const owoce = ["jabłko", "banan"];
console.log("Przed push:", owoce);
const nowaDlugosc = owoce.push("pomarańcza");
console.log("Po push:", owoce);
console.log("Nowa długość:", nowaDlugosc); // 3
// Push wielu elementów
owoce.push("gruszka", "śliwka");
console.log("Po wielu push:", owoce);
// 2. POP - usuń z końca
const warzywa = ["marchew", "brokuł", "pomidor"];
console.log("Przed pop:", warzywa);
const usuniety = warzywa.pop();
console.log("Usunięty:", usuniety); // "pomidor"
console.log("Po pop:", warzywa);
// Pop z pustej tablicy
const pusta = [];
const usunPusty = pusta.pop();
console.log("Pop z pustej:", usunPusty); // undefined
// 3. SHIFT - usuń z początku
const liczby = [1, 2, 3, 4, 5];
console.log("Przed shift:", liczby);
const pierwszy = liczby.shift();
console.log("Usunięty pierwszy:", pierwszy); // 1
console.log("Po shift:", liczby);
// 4. UNSHIFT - dodaj na początek
const kolory = ["zielony", "niebieski"];
console.log("Przed unshift:", kolory);
const nowaDl = kolory.unshift("czerwony");
console.log("Po unshift:", kolory);
console.log("Nowa długość:", nowaDl);
// Unshift wielu elementów
kolory.unshift("fioletowy", "żółty");
console.log("Po wielu unshift:", kolory);
// Push jest szybszy - dodaje na koniec
// Unshift jest wolniejszy - musi przesunąć wszystkie elementy
const duza = [];
console.time("push 10000");
for (let i = 0; i < 10000; i++) {
duza.push(i);
}
console.timeEnd("push 10000");
const duza2 = [];
console.time("unshift 10000"); // Mniej bo wolniejsze
for (let i = 0; i < 10000; i++) {
duza2.unshift(i);
}
console.timeEnd("unshift 1000");WAŻNE
Tablica z przypisaną tablicą będzie dalej jedną i tą samą tablicą !!!!
- Tablice (i obiekty) w JS są przechowywane w pamięci jako obiekty, a zmienne przechowują referencję do nich.
- Przypisanie jednej tablicy do drugiej nie kopiuje jej, tylko tworzy drugi wskaźnik do tej samej tablicy.
- Aby mieć niezależną kopię, trzeba jawnie skopiować tablicę.
METODY TABLICOWE CD.
| Metoda | Zwraca | Uwagi |
|---|---|---|
forEach |
nic (undefined) |
tylko wykonuje akcję |
map |
nowa tablica | każdy element przetwarzany |
filter |
nowa tablica | tylko elementy spełniające warunek |
find |
element | pierwszy pasujący element |
reduce |
jedna wartość | kumuluje/tablicę do wartości |
forEach→ robisz coś dla każdego elementu, nic nie zwraca.map→ tworzysz nową tablicę z przetworzonymi elementami.filter→ tworzysz nową tablicę, ale tylko z elementami spełniającymi warunek.find→ szukasz pierwszego pasującego elementu.reduce→ redukujesz tablicę do jednej wartości.
array.forEach(el => {/* coś robisz */});
array.map(el => /* zwracasz nowy element */);
array.filter(el => /* true/false */);
array.find(el => /* true/false */);
array.reduce((acc, el) => /* nowa wartość */, początkowa_wartość);el→ pojedynczy element tablicyacc→ accumulator wreduce -czyli zmienna, która „zbiera” wynik pośredni podczas przechodzenia po tablicy.początkowa_wartość→ np.0dla sumy
| Metoda | Co robi | Przykład |
|---|---|---|
find() |
pierwszy element spełniający warunek | [1,2,3].find(x=>x>1) → 2 |
findIndex() |
indeks elementu | [1,2].findIndex(x=>x>1) → 1 |
includes() |
czy tablica zawiera wartość | [1,2].includes(2) → true |
indexOf() |
indeks wartości | [1,2].indexOf(2) → 1 |
some() |
czy jeden spełnia warunek | [1,2].some(x=>x>1) → true |
every() |
czy wszystkie spełniają warunek | [1,2].every(x=>x>0) → true |
UWAGA kolejność ma znaczenie – jeśli mielibyśmy filtrowanie danych i mapowanie nowych wartości na dane to najpierw trzeba zrobić filtrowanie (bo zwróci mniej elementów), to się bardziej opłaca
TE I INNE
| Grupa | Metoda / Operator | Co robi / opis |
|---|---|---|
| Dodawanie / usuwanie elementów | push() |
dodaje elementy na końcu tablicy |
pop() |
usuwa ostatni element | |
shift() |
usuwa pierwszy element | |
unshift() |
dodaje elementy na początku tablicy | |
splice(start, deleteCount, ...items) |
usuwa lub dodaje elementy w środku tablicy | |
slice(start, end) |
zwraca fragment tablicy, nie modyfikuje oryginału | |
fill(value, start?, end?) |
wypełnia tablicę wartością w podanym zakresie | |
copyWithin(target, start, end?) |
kopiuje fragment tablicy w inne miejsce w tej samej tablicy | |
| Iteracja / przekształcanie | forEach(callback) |
wykonuje funkcję dla każdego elementu (nie tworzy nowej tablicy) |
map(callback) |
tworzy nową tablicę z przekształconymi elementami | |
filter(callback) |
tworzy nową tablicę z elementami spełniającymi warunek | |
reduce(callback, initialValue) |
redukuje tablicę do jednej wartości | |
reduceRight(callback, initialValue) |
redukuje tablicę od końca do jednej wartości | |
flatMap(callback) |
mapuje i spłaszcza wynik | |
| Szukanie / sprawdzanie | find(callback) |
zwraca pierwszy element spełniający warunek |
findIndex(callback) |
zwraca indeks pierwszego elementu spełniającego warunek | |
some(callback) |
czy przynajmniej jeden element spełnia warunek | |
every(callback) |
czy wszystkie elementy spełniają warunek | |
includes(value) |
sprawdza, czy tablica zawiera wartość | |
indexOf(value) |
zwraca indeks pierwszego wystąpienia wartości | |
lastIndexOf(value) |
zwraca indeks ostatniego wystąpienia wartości | |
| Łączenie / modyfikacja struktury | concat(...arrays) |
łączy tablice w nową tablicę |
join(separator) |
łączy elementy tablicy w string | |
reverse() |
odwraca kolejność elementów (modyfikuje tablicę) | |
sort([compareFunction]) |
sortuje elementy tablicy (rosnąco domyślnie, można podać funkcję) | |
toString() |
zamienia tablicę na string | |
toLocaleString() |
zamienia tablicę na string wg lokalizacji | |
| Tablice wielowymiarowe / płaskie | flat(depth?) |
spłaszcza tablicę wielowymiarową |
Array.isArray(value) |
sprawdza, czy wartość jest tablicą | |
| Dodatkowe narzędzia | keys() |
zwraca iterator kluczy (indeksów) tablicy |
values() |
zwraca iterator wartości tablicy | |
entries() |
zwraca iterator par [indeks, wartość] | |
findLast(callback) |
zwraca ostatni element spełniający warunek (nowa metoda ES2022) | |
findLastIndex(callback) |
zwraca indeks ostatniego elementu spełniającego warunek | |
| Operator | ... (spread) |
rozpakowuje elementy tablicy np. do nowej tablicy lub funkcji |
SORT
array.sort((a, b) => /* coś */);- Domyślnie sortuje elementy jako stringi
- Czasem wyniki są nieoczekiwane dla liczb:
[10,2,1].sort()→[1,10,2]
SORT Z COMPARE FUNCTION
array.sort((a, b) => /* coś */);a i b — dwie kolejne wartości do porównania
Funkcja musi zwrócić liczbę:
< 0 → a przed b
0 → kolejność bez zmian
0 → b przed a
OBIEKTY
Obiekty to struktury danych złożone z par klucz–wartość.
Służą do przechowywania informacji o rzeczach, które mają różne właściwości.
Przykład: użytkownik, samochód, produkt itp.
Do czego służy literał obiektu?
- szybkie tworzenie obiektów,
- przechowywanie danych,
- grupowanie powiązanych informacji,
- dodawanie metod (funkcji wewnątrz obiektu).
const person = {
name: "Ala",
age: 20,
greet() {
console.log("Cześć!");
}
};- klucz: wartość
- klucze oddzielamy przecinkami
- wartości mogą być: liczby, stringi, tablice, funkcje itd.
W obiekcie może być umieszczona tablica czy inny obiekt, funkcje (które jeśli są związane z obiektem nazywa się metodami – wtedy używają one słowa this).
Metoda obiektu = funkcja w środku obiektu, która mówi, co ten obiekt potrafi zrobić. Sposób zapisywania funkcji jako właściwości obiektu:
dodaj: function(liczba) {
...
}const kalkulator = {
wynik: 0,
dodaj: function(liczba) {
this.wynik = this.wynik + liczba; // kalkulator.wynik += liczba;
return this.wynik;
},
odejmij: function(liczba) {
this.wynik = this.wynik - liczba;
return this.wynik;
},
pomnoz: function(liczba) {
this.wynik = this.wynik * liczba;
return this.wynik;
},
reset: function() {
this.wynik = 0;
return this.wynik;
}// Używanie metod
console.log("Start:", kalkulator.wynik); // Wyświetli: 0
kalkulator.dodaj(5);
console.log("Po dodaniu 5:", kalkulator.wynik); // Wyświetli: 5
kalkulator.pomnoz(3);
console.log("Po pomnożeniu przez 3:", kalkulator.wynik); // Wyświetli: 15
kalkulator.odejmij(5);
console.log("Po odjęciu 5:", kalkulator.wynik); // Wyświetli: 10
kalkulator.reset();
console.log("Po resecie:", kalkulator.wynik); // Wyświetli: 0
Najpierw tworzysz obiekt (a w nim zapisujesz metody), a dopiero później możesz je wywołać.
const ksiazka = {
tytul: "Pan Tadeusz",
autor: "Adam Mickiewicz",
rok: 1834,
liczbaStron: 500,
ISBN10: "1234567890",
kategoria: ["epopeja narodowa","rymowane"],
changeISBN: function(newISBN) {
this.ISBN10 = newISBN;
console.log("obiekt po zmianie:", this);
return true;
}
};
if(ksiazka.changeISBN("0987654321")){
console.log("Zmiana powiodła się");
} else {
console.log("Zmiana nie powiodła się");
}
//ksiazka.changeISBN("0987654321");To działa dokładnie tak samo jak z funkcjami:
- najpierw „tworzysz” funkcję,
- potem ją wywołujesz.
METODY OBIEKTU
| Metoda | Co robi | Przykład |
|---|---|---|
Object.keys(obj) |
Zwraca tablicę kluczy obiektu | Object.keys({a:1,b:2}) // ["a","b"] |
Object.values(obj) |
Zwraca tablicę wartości obiektu | Object.values({a:1,b:2}) // [1,2] |
Object.entries(obj) |
Zwraca tablicę [klucz, wartość] | Object.entries({a:1,b:2}) // [["a",1],["b",2]] |
Object.assign(target, ...sources) |
Kopiuje właściwości z obiektów źródłowych do celu | Object.assign({}, {a:1},{b:2}) // {a:1,b:2} |
Object.create(proto) |
Tworzy nowy obiekt z podanym prototypem | Object.create(Array.prototype) |
Object.freeze(obj) |
Blokuje modyfikację obiektu | Object.freeze({a:1}) |
Object.seal(obj) |
Blokuje dodawanie/usuwanie właściwości (ale można zmieniać istniejące) | Object.seal({a:1}) |
Object.is(value1, value2) |
Porównuje wartości jak ===, ale z lepszą obsługą NaN i -0 |
Object.is(NaN, NaN) // true |
Object.getOwnPropertyNames(obj) |
Zwraca tablicę wszystkich własnych nazw właściwości (łącznie z nieenumerable) | Object.getOwnPropertyNames({a:1}) // ["a"] |
Object.getOwnPropertyDescriptors(obj) |
Zwraca opis właściwości (property descriptors) | Object.getOwnPropertyDescriptors({a:1}) |
Object.hasOwn(obj, prop) |
Sprawdza, czy obiekt ma własną właściwość | Object.hasOwn({a:1}, "a") // true |
Object.defineProperty(obj, prop, descriptor) |
Definiuje lub zmienia właściwość z dokładnym opisem | Object.defineProperty({}, "a",{value:1,writable:true}) |
Object.defineProperties(obj, descriptors) |
Definiuje wiele właściwości naraz | Object.defineProperties(obj,{a:{value:1}}) |
Object.fromEntries(array) |
Tworzy obiekt z tablicy [klucz, wartość] | Object.fromEntries([["a",1],["b",2]]) // {a:1,b:2} |
🔹 Object.keys(obj)
Zwraca tablicę kluczy obiektu.
Służy do sprawdzania, jakie właściwości obiekt posiada.
🔹 Object.values(obj)
Zwraca tablicę wartości z obiektu.
Używamy, gdy interesują nas tylko dane, bez nazw kluczy.
🔹 Object.entries(obj)
Zwraca tablicę par [klucz, wartość].
Przydatne, gdy chcesz iterować po obiekcie w formie listy.
const person = {
name: "Ala",
age: 20,
city: "Kraków"
};
console.log(Object.keys(person));
// ["name", "age", "city"]
console.log(Object.values(person));
// ["Ala", 20, "Kraków"]
console.log(Object.entries(person));
// [["name","Ala"], ["age",20], ["city","Kraków"]]estructuring (destrukturyzacja) obiektu w JS
- Destrukturyzacja pozwala wyciągnąć właściwości obiektu do zmiennych w jednej linijce.
- Dzięki temu nie trzeba pisać np.
const x = obj.x; const y = obj.y;.
const { właściwość1, właściwość2 } = obiekt;
gdzie:
właściwość1, właściwość2 → nazwy właściwości obiektu, które chcemy „wyciągnąć”
obiekt → obiekt, z którego pobieramy wartości
Property descriptors to „ukryte ustawienia”, które opisują, jak zachowuje się dana właściwość obiektu w JavaScript.
Każda właściwość ma dodatkowe cechy, takie jak:
- writable – czy można zmieniać wartość
- enumerable – czy właściwość pokazuje się w pętli
for...inlub wObject.keys() - configurable – czy można ją usunąć lub zmienić jej ustawienia
- (opcjonalnie) get / set – funkcje pobierające i ustawiające wartość
To nie są rzeczy, które widzisz na co dzień — ale JavaScript używa ich pod spodem, by kontrolować działanie obiektów.
Klasy w JavaScripcie to specjalny sposób tworzenia obiektów i ich „szablonów”.
Prosto mówiąc:
- Klasa to przepis na obiekt.
- Na podstawie klasy możesz tworzyć wiele obiektów, które mają te same właściwości i funkcje (metody).
Po co są?
- Żeby łatwo tworzyć wiele podobnych obiektów.
- Żeby uporządkować kod, szczególnie gdy obiekty mają zachowania (metody).
- Żeby kod był czytelniejszy i bardziej „poukładany”.
Syntax sugar – opakowanie na istniejący język prototypów (klasy: pod spodem prototypy – ale czytelniejsza składnia)
w klasach nie mówimy o prototypie ale o klasach, konstruktorach i instancjach klas
Konstruktor — „budowniczy” obiektu
Konstruktor to specjalna funkcja wewnątrz klasy, która uruchamia się automatycznie, gdy tworzysz obiekt na podstawie tej klasy.
To on:
- przyjmuje dane (np. marka, model),
- zapisuje je w obiekcie,
- przygotowuje obiekt do działania.
W kodzie jest to funkcja o nazwie constructor().
Instancja — „konkretna sztuka” obiektu
Instancja (ang. instance) to konkretny obiekt stworzony na podstawie klasy.
Jeśli klasa jest przepisem, to instancja jest konkretnym daniem zrobionym według tego przepisu.
Podsumowanie w 1 zdaniu
- Klasa – przepis
- Konstruktor – kucharz przygotowujący potrawę
- Instancja – gotowa potrawa
Klasy – świetne kiedy powtarzają się komponenty na stronach, klasa to rozwinięcie prototypu
Nazwa klasy jest zawsze z dużej litery (nie tak jak zmienne)/ Pascal Case
this → wskazuje na obiekt, który właśnie tworzysz albo którego używasz, używa się go dla każdej nowej instancji
new → zaczyna proces tworzenia nowego obiektu.
class Osoba {
constructor(imie, wiek) {
// this wskazuje na nowo tworzony obiekt
this.imie = imie;
this.wiek = wiek;
}
przywitaj() {
// this wskazuje na obiekt, który wywołał tę metodę
console.log(`Cześć, jestem ${this.imie} i mam ${this.wiek} lat.`);
}
}
// użycie new — tworzymy nową instancję klasy
const osoba1 = new Osoba("Kasia", 25);
// metoda używa this — odnosi się do obiektu osoba1
osoba1.przywitaj();
Metody dla instancji tworzymy bez słowa function np. przywitaj() {}
UWAGA Klasy muszą być zadeklarowane przed ich użyciem!!!
Jak sięgnąć do właściwości konkretnych obiektów – posługując się zamienną, w której pojawiło się new.
Piszemy nazwę zmiennej – kropka – nazwa lub nazwa w nawiach[], jeśi jest zmienną np.:
osoba1.imie lub osoba1[‘Kasia’]
Jedna metoda dla klasy obsługuje wszystkie obiekty. Tworzenie metody dla klasy w JavaScript jest bardzo proste — po prostu dodajesz ją wewnątrz ciała klasy, ale poza konstruktorem.
Metoda to po prostu funkcja zapisana w klasie, która automatycznie ma dostęp do this (czyli właściwości obiektu).
Metody statyczne
Metody statyczne to takie metody w klasie, które należą do samej klasy, a nie do jej obiektów. Metoda statyczna = funkcja klasy, a nie funkcja obiektu.
❗ Metod statycznych NIE wywołujesz na obiekcie.
- Metoda statyczna to narzędzie klasy,
a nie „czynność” wykonywana przez konkretny obiekt. - Nie ma dostępu do this w sensie obiektu,
bo nie działa na obiekcie.
Kiedy używać metod statycznych?
✔ Gdy metoda nie dotyczy konkretnego obiektu, tylko kategorii / klasy jako całości.
Przykłady:
- funkcje matematyczne (suma, losowanie, zaokrąglanie) np. Math.random
- tworzenie obiektów w specjalny sposób (fabryki- Fabryka obiektów to po prostu funkcja lub metoda, która tworzy i zwraca nowe obiekty. Mówiąc prosto: zamiast pisać wielokrotnie new Klasa(...), możesz mieć jedną funkcję, która automatycznie generuje obiekty według przepisu.)
- porównywanie dwóch obiektów
- narzędzia pomocnicze
| Typ metody | Deklaracja | Wywołanie | Przykład |
|---|---|---|---|
| Instancyjna | bez static |
na obiekcie | js class Person { greet() { console.log("Cześć"); } } const p = new Person(); p.greet(); |
| Statyczna | static |
na klasie | js class MathUtils { static add(a,b){ return a+b; } } console.log(MathUtils.add(2,3)); |
| Prywatna | # przed nazwą |
tylko w klasie | js class Secret { #show(){ return "tajne"; } reveal(){ console.log(this.#show()); } } const s = new Secret(); s.reveal(); // działa, s.#show(); ❌ błąd |
|
Typ pola* |
Dla kogo? |
Jak dostęp? |
|
zwykłe (this.imie) |
dla obiektu |
obiekt.imie |
|
statyczne (static licznik) |
dla klasy |
Klasa.licznik |
|
prywatne (#wiek) |
dla klasy, wewnątrz metod |
this.#wiek |
Pole klasy = zmienna powiązana albo z obiektem, albo z klasą
-Przechowuje dane, które opisują obiekt (zwykłe) lub klasę (statyczne)
-Prywatne pola = dane ukryte, dostępne tylko w metodach klasy
W JavaScripcie super używa się w kontekście dziedziczenia klas.
Mówiąc prosto, pozwala odwołać się do rodzica klasy — zarówno do jego konstruktora, jak i do metod.
super() w konstruktorze
- Gdy tworzysz klasę potomną (dziedziczącą), możesz użyć super(), żeby wywołać konstruktor klasy rodzica.
- Dzięki temu nie musisz przepisywać kodu rodzica, tylko przekazujesz mu potrzebne dane.
- Super występuje przed this?
W JavaScripcie, gdy klasa dziecka ma własny konstruktor i jeśli nie wywołasz super(), to:
- Konstruktor rodzica (Zwierze) nie zostanie uruchomiony.
- this w klasie dziecka nie istnieje jeszcze i próba ustawienia this.imie lub użycia this wyrzuci błąd.
Super istnieje w parze z extends:
-super w JS służy do wywołania konstruktora lub metod klasy rodzica.
-Klasa rodzica istnieje tylko wtedy, gdy używasz extends, czyli dziedziczenia.
// Klasa bazowa
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} wydaje dźwięk`);
}
}
// Klasa potomna dziedzicząca po Animal
class Dog extends Animal {
constructor(name, breed) {
super(name); // wywołuje konstruktor klasy bazowej
this.breed = breed;
}
speak() {
super.speak(); // wywołuje metodę speak() z klasy bazowej
console.log(`${this.name} szczeka`);
}
}
const dog = new Dog("Burek", "Owczarek");
dog.speak();Enkapsulacja (z ang. encapsulation) to zasada programowania obiektowego, która polega na ukrywaniu szczegółów wewnętrznych obiektu i udostępnianiu tylko tego, co jest potrzebne na zewnątrz.
Mówiąc prosto:
„Schowaj wewnętrzne dane i pozwól innym korzystać z nich tylko przez określone metody.”
Dlaczego to ważne?
- Chroni dane obiektu przed niepożądaną zmianą z zewnątrz.
- Pozwala kontrolować jak można modyfikować lub odczytywać dane.
- Ułatwia utrzymanie i rozwój kodu — zmiany wewnątrz klasy nie psują reszty programu, jeśli interfejs (metody) się nie zmienia.
class BankAccount {
#balance = 0; // prywatna właściwość
constructor(initialBalance) {
this.#balance = initialBalance;
}
// publiczna metoda do wpłaty
deposit(amount) {
if(amount > 0) this.#balance += amount;
}
// publiczna metoda do sprawdzenia stanu konta
getBalance() {
return this.#balance;
}
}
const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
// Próba dostępu do prywatnego pola
console.log(account.#balance); // ❌ Błąd!| Cecha | Metody klasy | Metody obiektu |
|---|---|---|
| Gdzie są deklarowane | W klasie (class) |
W obiekcie literalnym (const obj = { ... }) |
| Do czego należą | Do instancji lub do klasy (statyczne) | Do konkretnego obiektu |
| Wywołanie | - Instancyjne: obj.method() - Statyczne: Class.method() |
obj.method() |
| Tworzenie nowych instancji | Można tworzyć wiele obiektów z tej samej klasy, wszystkie dzielą prototypowe metody | Każdy obiekt literalny ma własne metody; nie są współdzielone automatycznie |
| Prywatność | Prywatne metody #method dostępne tylko w klasie |
Prywatność zwykle symulowana przez zamknięcia (closure), brak wbudowanej składni # w starszych wersjach |
| Dziedziczenie | extends pozwala tworzyć klasy potomne z tymi samymi metodami |
Trzeba ręcznie kopiować metody lub używać prototypów |
Prototypy w JS – co to jest
- Prototyp to obiekt, z którego inne obiekty dziedziczą właściwości i metody.
- Każdy obiekt w JS ma ukryte powiązanie z innym obiektem – jego prototypem (
[[Prototype]]). - Dzięki temu można współdzielić metody między wieloma obiektami, zamiast tworzyć je w każdym obiekcie osobno.
- Tworzysz obiekt:
const person = { name: "Ala" };
- Możesz sprawdzić jego prototyp:
console.log(Object.getPrototypeOf(person)); // np. Object.prototype
- eśli próbujesz użyć właściwości/metody, której obiekt nie ma, JS sprawdza prototyp i dalej w jego łańcuchu (chain), aż do
null.
console.log(person.toString()); // działa, bo toString jest w Object.prototype
Składnia dodawania metod do prototypu
function Person(name) { this.name = name;
}// Dodanie metody do prototypu) {
Person.prototype.greet = function( console.log(`Cześć, mam na imię ${this.name}`);
};const p = new Person("Ala");p.greet(); // "Cześć, mam na imię Ala"
pnie ma własnej metodygreet, ale dziedziczy ją z prototypu klasy/funkcji.