Lekcja 8: Obiekty
Obiekty (Objects) to fundamentalna koncepcja w JavaScript. Są to złożone typy danych, które pozwalają na przechowywanie kolekcji danych w postaci par klucz-wartość. Klucze (nazywane też właściwościami lub polami) są zazwyczaj stringami (lub symbolami), a wartości mogą być dowolnego typu danych, w tym innymi obiektami lub funkcjami (wtedy nazywamy je metodami).
Tworzenie obiektów
Istnieje kilka sposobów tworzenia obiektów:
1. Literał obiektowy (Object Literal)
Najprostszy i najczęściej używany sposób.
// Pusty obiekt
let pustyObiekt = {};
// Obiekt z właściwościami
let osoba = {
imie: "Jan",
nazwisko: "Kowalski",
wiek: 30,
czyAktywny: true,
adres: { // Zagnieżdżony obiekt
ulica: "Kwiatowa",
numer: 15
},
// Metoda (funkcja jako właściwość)
przedstawSie: function() {
// 'this' odnosi się do obiektu 'osoba'
console.log(`Nazywam się ${this.imie} ${this.nazwisko} i mam ${this.wiek} lat.`);
},
// Skrócony zapis metody (ES6)
pozdrów() {
console.log(`Witaj od ${this.imie}!`);
}
};
console.log(osoba);
2. Konstruktor `Object()`
let samochod = new Object();
samochod.marka = "Toyota";
samochod.model = "Corolla";
samochod.rok = 2022;
console.log(samochod);
Ten sposób jest rzadziej używany niż literał obiektowy.
3. Funkcje konstruktora
Można tworzyć własne funkcje, które działają jak "szablony" do tworzenia obiektów (omówimy to szerzej w kontekście prototypów i klas).
function Car(marka, model, rok) {
this.marka = marka;
this.model = model;
this.rok = rok;
this.wyswietlInfo = function() {
console.log(`${this.marka} ${this.model} (${this.rok})`);
}
}
let auto1 = new Car("Ford", "Mustang", 2023);
let auto2 = new Car("BMW", "X5", 2021);
auto1.wyswietlInfo(); // Ford Mustang (2023)
auto2.wyswietlInfo(); // BMW X5 (2021)
Dostęp do właściwości
Do właściwości obiektu można odwoływać się na dwa sposoby:
1. Notacja kropkowa (`.`)
Najczęstszy sposób, gdy nazwa właściwości jest znanym, poprawnym identyfikatorem JavaScript.
let osoba = { imie: "Anna", wiek: 28 };
console.log(osoba.imie); // "Anna"
console.log(osoba.wiek); // 28
// Modyfikacja właściwości
osoba.wiek = 29;
console.log(osoba.wiek); // 29
// Dodanie nowej właściwości
osoba.zawod = "Programistka";
console.log(osoba.zawod); // "Programistka"
2. Notacja nawiasowa (`[]`)
Wymagana, gdy nazwa właściwości nie jest poprawnym identyfikatorem (np. zawiera spacje, zaczyna się od cyfry) lub gdy nazwa właściwości jest przechowywana w zmiennej.
let produkt = {
"nazwa produktu": "Laptop",
"numer seryjny": "XYZ123",
cena: 4500
};
console.log(produkt["nazwa produktu"]); // "Laptop"
console.log(produkt["numer seryjny"]); // "XYZ123"
let klucz = "cena";
console.log(produkt[klucz]); // 4500
// Dodanie właściwości z dynamiczną nazwą
let nowaWlasciwosc = "kolor";
produkt[nowaWlasciwosc] = "srebrny";
console.log(produkt.kolor); // "srebrny"
Wywoływanie metod
Metody obiektu wywołuje się podobnie jak zwykłe funkcje, używając notacji kropkowej lub nawiasowej, a następnie nawiasów `()`.
let osoba = {
imie: "Jan",
przedstawSie: function() {
console.log(`Jestem ${this.imie}.`);
}
};
osoba.przedstawSie(); // Wywołanie metody - "Jestem Jan."
Słowo kluczowe `this`
Wewnątrz metody obiektu, słowo kluczowe `this` odnosi się do obiektu, na którym metoda została wywołana. Pozwala to metodzie na dostęp do innych właściwości tego samego obiektu.
Zachowanie `this` może być skomplikowane, szczególnie w funkcjach strzałkowych i przy różnych sposobach wywoływania funkcji (omówimy to dokładniej w przyszłości).
Iterowanie po właściwościach obiektu
Do iterowania po kluczach obiektu używamy pętli `for...in`.
let samochod = {
marka: "Fiat",
model: "Panda",
rok: 2019
};
for (const klucz in samochod) {
// Sprawdzenie, czy właściwość należy bezpośrednio do obiektu (a nie do prototypu)
if (samochod.hasOwnProperty(klucz)) {
console.log(`${klucz}: ${samochod[klucz]}`);
}
}
// Wynik:
// marka: Fiat
// model: Panda
// rok: 2019
Inne metody iteracji (ES6+):
Object.keys(obj)
: Zwraca tablicę kluczy obiektu.Object.values(obj)
: Zwraca tablicę wartości obiektu.Object.entries(obj)
: Zwraca tablicę par [klucz, wartość].
console.log(Object.keys(samochod)); // ["marka", "model", "rok"]
console.log(Object.values(samochod)); // ["Fiat", "Panda", 2019]
console.log(Object.entries(samochod)); // [["marka", "Fiat"], ["model", "Panda"], ["rok", 2019]]
// Użycie z for...of
for (const klucz of Object.keys(samochod)) {
console.log(`Klucz: ${klucz}`);
}
for (const [klucz, wartosc] of Object.entries(samochod)) {
console.log(`${klucz} -> ${wartosc}`);
}
Usuwanie właściwości
Operator `delete` usuwa właściwość z obiektu.
let dane = { a: 1, b: 2, c: 3 };
console.log(dane); // { a: 1, b: 2, c: 3 }
delete dane.b;
console.log(dane); // { a: 1, c: 3 }
Zadanie praktyczne
Stwórz obiekt reprezentujący książkę, zawierający właściwości: `tytul`, `autor`, `rokWydania` oraz metodę `wyswietlSzczegoly`, która wyświetli w konsoli pełne informacje o książce w czytelnym formacie.
Pokaż rozwiązanie
let ksiazka = {
tytul: "Władca Pierścieni",
autor: "J.R.R. Tolkien",
rokWydania: 1954,
wyswietlSzczegoly: function() {
console.log("--- Szczegóły książki ---");
console.log(`Tytuł: ${this.tytul}`);
console.log(`Autor: ${this.autor}`);
console.log(`Rok wydania: ${this.rokWydania}`);
console.log("-------------------------");
}
};
// Wywołanie metody
ksiazka.wyswietlSzczegoly();
Zadanie do samodzielnego wykonania
Stwórz obiekt `koszyk` z kilkoma produktami jako właściwościami, gdzie kluczem jest nazwa produktu, a wartością jego cena (np. { "mleko": 3.50, "chleb": 4.00, "jajka": 8.00 }
). Następnie napisz kod, który używając pętli `for...in` lub `Object.entries()`, obliczy i wyświetli w konsoli łączną wartość produktów w koszyku.
FAQ - Obiekty
Jaka jest różnica między obiektem a tablicą?
Tablice są specjalnym typem obiektów, zoptymalizowanym do przechowywania uporządkowanych kolekcji danych dostępnych przez indeksy liczbowe. Zwykłe obiekty służą do przechowywania nieuporządkowanych kolekcji danych w postaci par klucz-wartość, gdzie klucze są stringami lub symbolami.
Czy kolejność właściwości w obiekcie jest gwarantowana?
Historycznie, kolejność właściwości nie była gwarantowana. Od ES2015, kolejność dla kluczy niebędących liczbami całkowitymi jest zachowana zgodnie z kolejnością dodawania. Klucze będące liczbami całkowitymi są zazwyczaj sortowane rosnąco. Nie należy jednak polegać na kolejności właściwości obiektu.
Kiedy używać notacji kropkowej, a kiedy nawiasowej?
Używaj notacji kropkowej (`.`) dla prostoty i czytelności, gdy klucz jest znanym, poprawnym identyfikatorem. Używaj notacji nawiasowej (`[]`), gdy klucz zawiera specjalne znaki, jest przechowywany w zmiennej lub jest obliczany dynamicznie.
Co to jest `hasOwnProperty()`?
Jest to metoda obiektu, która zwraca `true`, jeśli obiekt posiada określoną właściwość bezpośrednio (nie dziedziczoną z prototypu), a `false` w przeciwnym razie. Jest często używana w pętli `for...in`, aby upewnić się, że iterujemy tylko po własnych właściwościach obiektu.
Czy mogę używać liczb jako kluczy obiektu?
Tak, ale JavaScript automatycznie konwertuje liczbowe klucze na stringi. Kiedy używasz liczby jako klucza, np. obiekt[1] = wartosc
, klucz jest traktowany jak string "1".
Jak skopiować obiekt?
Proste przypisanie let kopia = oryginal;
tworzy tylko referencję, a nie kopię. Do płytkiego kopiowania (kopiowanie tylko właściwości pierwszego poziomu) można użyć `Object.assign({}, oryginal)` lub operatora spread `let kopia = { ...oryginal };`. Głębokie kopiowanie (kopiowanie również zagnieżdżonych obiektów) wymaga bardziej zaawansowanych technik lub bibliotek.