Class
Poza poznanymi w poprzednim rozdziale konstruktorami, do tworzenia własnych typów obiektów możemy też wykorzystać składnię class czyli klasy.
W niektórych miejscach internetu możesz natrafić na stwierdzenie, że klasy w Javascript są tak zwanym "syntactic sugar", co oznacza, że jest to tylko swego rodzaju nakładka na poznane w poprzednim rozdziale mechanizmy. Jest to poniekąd prawdą, ponieważ zasada działania poznana w poprzednim rozdziale w większości się nie zmienia, natomiast z pewnością upraszcza nam się kod, a i niektóre mechanizmy lekko się zmieniają.
Deklaracja klasy
Klasy są "specjalnymi funkcjami", które służą do tego samego co konstruktory. Ogólna deklaracja i użycie klasy ma postać:
class Animal {
constructor() {
...
}
eat() {
...
}
sleep() {
...
}
}
//obiekty tworzymy tak samo jak poprzednio
const pet1 = new Animal();
const pet2 = new Animal();
Podobnie do klasycznych funkcji definicję klasy możemy też stworzyć jako wyrażenie const Animal = class {}
, chociaż zapis taki jest raczej rzadko spotykany.
Gdy zbadasz sobie w konsoli powyższą klasę za pomocą console.dir(Animal)
, zobaczysz, że praktycznie jest ona tym samym co konstruktor z poprzedniego rozdziału. Tam była funkcja, i tu też jest funkcja. Tam konstruktor dostawał właściwość prototype
, na którą wskazywały [[Prototype]] w pojedynczych instancjach, to samo dzieje się i tutaj:

function AnimalFn() {
...
}
class Animal {
...
}
console.log(typeof Animal, typeof AnimalFn); //function, function
Object.getPrototypeOf(Animal) === Object.getPrototypeOf(AnimalFn) //true
class Animal {
...
}
const animal = new Animal();
Object.getPrototypeOf(animal) === Animal.prototype //true
constructor()
Każda klasa posiada specjalną funkcję constructor(), która jest automatycznie odpalana przy tworzeniu nowej instancji za pomocą słowa new.
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
console.log(`Zwierzak ${this.name} ma ${this.age} lata`);
}
method1() {
...
}
method2() {
...
}
}
const animal = new Animal("pies", 3); //Zwierzak pies ma 3 lata
Funkcja constructor()
jest w zasadzie tym samym, co używana w poprzednim zapisie funkcja będąca konstruktorem:
function User(name, age) {
this.name = name;
this.age = age;
}
//w nowej składni
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
Funkcja constructor()
wykorzystywana jest nie tylko do tworzenia właściwości nowych obiektów, ale też do automatycznego uruchamiania wybranych metod podczas tworzenia nowych obiektów:
class Table {
constructor() {
this.table = null;
this.createTable();
this.initEvent();
}
createTable() {
}
initEvents() {
}
mark() {
}
}
W kolejnych rozdziałach, gry już realnie zaczniemy pracować nad wybranymi projektami (np. 1, 2, 3) zobaczysz to w działaniu.
Dodawanie metod
Funkcje, które dodasz do danej klasy, automatycznie trafią do prototypu obiektów, które będziesz tworzył na jej podstawie:
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
eat() {
console.log(this.name + " jem");
}
sleep() {
console.log(this.name + " śpię");
}
}

W przeciwieństwie do obiektów budowanych na bazie konstruktorów metody takie nie będą uwzględniane, jeżeli po danym obiekcie zrobimy pętlę for in
, a i w przypadku klas każda metoda ma swoją właściwość name
, co może być kiedyś przydatne. Możesz to sprawdzić na przykładowej stronie.
Właściwości
Właściwości początkowe, które od razu pojawią się w obiektach budowanych na bazie danej klasy dodajemy zazwyczaj wewnątrz konstruktora:
class Animal {
constructor(name) {
this.name = name;
this.legs = 4;
this.type = "animal";
}
show() {
console.log(`Zwierze nazywa się ${this.name} i ma ${this.legs} nóg`);
}
}
const pet1 = new Animal("Koń");
Jeżeli dane właściwości nie wymagają przekazania wartości przy tworzeniu, możemy też je stworzyć bezpośrednio w ciele klasy:
//równoznaczne z powyższym kodem
class Car {
years = 0;
wheels = 4;
...
}
class Car {
years = 0;
wheels = 4;
constructor(color) {
this.color = color;
}
}
//jest równoznaczne jest z
class Car {
constructor(color) {
this.years = 0;
this.wheels = 4;
this.color = color;
}
}
Metody statyczne
Jeżeli stworzymy metody danej klasy, domyślnie trafią one do prototypu obiektów tworzonych na bazie tej klasy.
class Human {
constructor(name) {
this.name = name;
}
say() {
console.log("Jestem człowiek");
}
}
const ob = new Human("Marcin");
ob.say(); //"Jestem człowiek" - obiekt skorzystał z metody z prototypu
Możemy też tworzyć metody i właściwości statyczne. Nie są one dostępne dla pojedynczych instancji, ale możemy je w przyszłości uruchomić bezpośrednio poprzez daną klasę.
Takimi statycznymi funkcjonalnościami są najczęściej jakieś użyteczne funkcje, które będą zgrupowane w danej klasie.
Przykładami takich metod są Array.isArray()
, które odpalamy by sprawdzić czy dana wartość jest tablicą, czy chociażby Object.getPrototypeOf()
, która zwraca prototyp danego obiektu.
class Human {
constructor(name) {
this.name = name;
}
say() {
console.log("Jestem człowiek");
}
static printInfo() {
console.log("Ludzie są fajni");
}
}
Human.printInfo(); //"Ludzie są fajni"
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
static compareByName(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
static compareByAge(a, b) {
return a.age - b.age;
}
}
const users = [
new User("Tomek", 10),
new User("Ania", 35),
new User("Beata", 20),
new User("Monika", 20),
new User("Karol", 22)
];
users.sort( User.compareByName );
console.log( users[0].name ); // Ania
users.sort( User.compareByAge );
console.log( users[0].name ); // Tomek
Trening czyni mistrza
Jeżeli chcesz sobie potrenować zdobytą wiedzę, zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania