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
- 1,046