Wyjaśnij, jak działa dziedziczenie w JavaScript.
sobes.tech AI
Odpowiedź od AI
Dziedziczenie w JavaScript realizowane jest przez prototypy. Każdy obiekt w JavaScript ma właściwość wewnętrzną [[Prototype]], która odwołuje się do innego obiektu. Gdy próbujemy uzyskać dostęp do właściwości lub metody obiektu, którego nie ma bezpośrednio na nim, silnik JavaScript szuka tej właściwości lub metody w prototypie tego obiektu. Jeśli jej tam nie znajdzie, kontynuuje poszukiwania w łańcuchu prototypów, który jest tworzony przez połączenia [[Prototype]], aż do osiągnięcia null (końca łańcucha).
Istnieją dwa główne mechanizmy dziedziczenia:
-
Klasyczne dziedziczenie prototypowe (ES5 i wcześniejsze): Oparte na użyciu funkcji konstruktorów i ich właściwości
prototype.// Funkcja konstruktora function Animal(name) { this.name = name; } // Dodanie metody do prototypu Animal.prototype.speak = function() { console.log(`${this.name} wydaje dźwięk.`); }; // Tworzenie instancji const dog = new Animal('Pies'); // Wywołanie metody z prototypu dog.speak(); // Wyświetli: Pies wydaje dźwięk. // Prototyp cat to Animal.prototype console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true -
Dziedziczenie oparte na klasach (ES6 i nowsze): Używa składni
classiextends, które wewnętrznie nadal operują na prototypach.// Klasa bazowa class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} wydaje dźwięk.`); } } // Podklasa dziedzicząca po Animal class Dog extends Animal { constructor(name, breeds) { super(name); // Wywołanie konstruktora klasy nadrzędnej this.breeds = breeds; } bark() { console.log(`${this.name} szczeka.`); } } // Tworzymy instancję podklasy const myDog = new Dog('Bublik', ['Labrador', 'Collie']); // Wywołujemy metody zarówno z Animal, jak i z Dog myDog.speak(); // Wyświetli: Bublik wydaje dźwięk. myDog.bark(); // Wyświetli: Bublik szczeka. // Prototyp myDog to Dog.prototype console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // true // Prototyp Dog.prototype to Animal.prototype console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
Kluczowe koncepcje:
-
Łańcuch prototypów: Związek między obiektami przez ich
[[Prototype]]. -
__proto__(przestarzałe/niestandardowe, ale pomocne do zrozumienia): Właściwość, przez którą można uzyskać dostęp do[[Prototype]]. Nie zaleca się używania w produkcji. -
Object.getPrototypeOf(obj): Standardowy sposób uzyskania prototypu obiektu. -
Object.setPrototypeOf(obj, proto): Standardowy sposób zmiany prototypu obiektu (niezalecane do zmiany prototypu istniejących obiektów po ich utworzeniu). -
instanceof: Operator do sprawdzania, czy obiekt jest instancją klasy lub funkcji konstrukcyjnej, poprzez sprawdzenie jego łańcucha prototypów.console.log(myDog instanceof Dog); // true console.log(myDog instanceof Animal); // true console.log(myDog instanceof Object); // true (na końcu łańcucha Object.prototype) -
super: Używany w klasach do wywoływania metod lub konstruktora klasy nadrzędnej.
Różnica między podejściem klasycznym a opartym na klasach: Klasy zapewniają bardziej strukturalny i składniowo wygodny sposób pracy z dziedziczeniem prototypowym, zbliżony do innych języków programowania. Jednak podstawowy mechanizm pozostaje ten sam — dziedziczenie przez prototypy.