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

  • 938