Znajdź swoje korzenie
Dziedziczenie
w JavaScript
Agata Malec-Sromek
Agata Malec-Sromek
Czym się zajmuję?
Mentoruję, programuję a także
opiekuję się kursem Front-end-owym
agatajs
w
Jakim problemem się zajmiemy?
Klasa pochodna dziedziczy od klasy bazowej.
Obiekty są kopiami klas.
Klasyczny model dziedziczenia
Nie ma klas, są obiekty.
Obiekty dziedziczą od innych obiektów.
Prototypowy model dziedziczenia
Konkatenatywne dziedziczenie
(concatenative inheritance)
Delegowanie prototypów
(delegate prototypes)
"Classical and prototypal inheritance are fundamentally and semantically distinct."
If you don’t understand prototypes,
you don’t understand
JavaScript.
Podstawy
Obiekt
var alien = {
name: "jlSuDrup",
age: 14521,
sayHello: function () {
console.log("nuqneH");
}
};
Skąd tajemnicze
atrybuty?
Obiekty wbudowane
-
Number
-
Boolean
-
String
-
Array
-
Symbol
-
Date
-
Math
-
Object
Czym są
__proto__ i
[[Prototype]] ?
to wewnętrzna własność obiektu wskazująca na inny obiekt.
[[Prototype]]
Zapis specyfikacji
Niektóre specyfikacje JS umożliwiają dostęp do tej własności poprzez
__proto__
Ojciec wszystkich ojców
Object.prototype
Object.prototype
funkcja
obiekt
Każdy obiekt w JavaScript "dziedziczy" z obiektu wbudowanego Object.prototype
Prototype chain
Prototype chain
Jak działa prototype chain
Konstruktory
symulacja klas
Kolejny prototyp
Czym jest prototype?
Alien.prototype
function Alien(name) {
this.name = name;
}
console.dir(Alien);
Każda funkcja w JavaScript otrzymuje podczas tworzenia własność prototype.
Funkcja
Obiekt
function Alien(name) {
this.name = name;
}
Alien.prototype.sayHello = function(text) {
console.log(text);
}
console.dir(Alien);
Do prototypu mogę dodawać własne zachowania i atrybuty
function Alien(name) {
this.name = name;
}
Alien.prototype.sayHello = function(text) {
console.log(text);
}
var alienA = new Alien("Clark");
var alienB = new Alien("Optimus Prime");
alienA.sayHello("Hello"); //Hello
alienB.sayHello("nuqneH"); //nuqneH
Poznajmy
new
Co robi new?
Dodajmy "klasę" pochodną
function Alien(name) {
this.name = name;
}
Alien.prototype.sayHello = function(text) {
console.log(text);
}
function AlienFromMars(name) {
Alien.call(this, name);
this.color = "red";
}
AlienFromMars.prototype.fly = function() {
console.log('I can fly!');
}
"Klasa
pochodna"
"Klasa
bazowa"
Stworzyliśmy klasę pochodną
... ale w żaden sposób nie jest ona połączona z klasą bazową Alien.
Pierwsza myśl
AlienFromMars.prototype = Alien.prototype
ale to nie jest dobry pomysł
var alienA = new AlienFromMars('clark');
var alienB = new Alien("Optimus Prime");
AlienFromMars.prototype.sayHello = function(){
console.log("No!");
}
alienA.sayHello(); // No!
alienB.sayHello(); // No!
Nadpisujemy ten sam obiekt!
Text
Co teraz?
A gdyby tak, można było zrobić samo połączenie
... bez tej całej "zagmatwanej plątaniny"
[[Prototype]]
A
B
Obiekt B jest połączony z A
var A = {};
var B = Object.create(A);
function Alien(name) {
this.name = name;
}
Alien.prototype.sayHello = function(text) {
console.log(text);
}
function AlienFromMars(name) {
Alien.call(this, name);
this.color = "green";
}
AlienFromMars.prototype = Object.create(Alien.prototype)
to jest obiekt !
Object.create()
Wygląda dobrze, ale coś wciąż jest nie tak
Konstruktor wskazuje na Alien
dopisanie odpowiednich metod ... i
AlienFromMars.prototype.constructor = AlienFromMars;
AlienFromMars.prototype.fly = function() {
console.log('I can fly!');
}
Huh, działa....
Kilka słów o
new
Dziedziczenie przez delegowanie
var Alien = {
sayHello: function(text) {
console.log(text);
}
}
var AlienFromMars = Object.create(Alien);
AlienFromMars.fly = function() {
console.log('Umiem latać');
}
var alienA = Object.assign(Object.create(AlienFromMars), {
name: "Clark"
});
var alienB = Object.create(Alien, {
name: {value: "Optimus Prime" }
});
Concatenative inheritance
Factory function
Funkcje mogą tworzyć i zwracać obiekty. Jeśli taka funkcja nie jest wywołana za pomocą new to jest określana jako factory function
Factory function
var Alien = {
sayHello: function(text) {
console.log(text);
}
}
var alienFromMars = function (name) {
return Object.assign(Object.create(Alien), {
fly: function() { console.log('Umiem latać') },
color: 'red',
name: name
});
};
var alienA = alienFromMars("Clark");
var alienB = Object.assign(Object.create(Alien), {
name: 'Optimus Prime'
})
Factory function
Klasy - lukier
Hura Klasy!
class Alien {
constructor(name) {
this.name = name;
}
sayHello(text) {
console.log(text)
}
}
class AlienFromMars extends Alien {
fly() {
console.log('Umiem latać')
}
}
var alienA = new Alien("Clark");
var alienB = new AlienFromMars("Optimus Prime");
Kod wygląda
przyjemnie, ale ...
"pod spodem"
wciąż mamy do czynienia z prototypami!
Ilustracje
Emilia Mucha
Dziękuję :)
Inne języki prototypowe
Io - http://iolanguage.org/
Common Lisp - https://common-lisp.net/
Znajdź swoje korzenie - dziedziczenie w JavaScript
By Agata Malec
Znajdź swoje korzenie - dziedziczenie w JavaScript
4developers
- 961