Dziedziczenie w JavaScript – część 3

Na pewno  sporo z was wie jak dużo jest niezrozumienia pomiędzy tym czy używać w JavaScript konstruktorów czy nie.
A odkąd możemy korzystać ze słowa class w ES6 to wielu ludzi myśli, że to rozwiązuje wszystkie problemy związane z konstruktorami – a tak niestety nie jest.

W tym wpisie poznamy dwie metody dziedziczenia w JavaScript: Delegate prototype oraz  Concatenative Inheritance i skupimy się  na tym, żeby je dobrze zrozumieć.

Wstęp

Ale żeby dobrze zrozumieć ten temat musimy bardzo dobrze wiedzieć jak wyglądają obiekty w  JavaScript i czym jest [[Prototype]] oraz prototype. Także jeśli ktoś z was jeszcze nie czytał to zachęcam zajrzeć do wpisów Dziedziczenie w JavaScript – część 1 oraz Dziedziczenie w JavaScript – część 2

Object.create()

Na początek będzie nam potrzebna znajomość funkcji Object.create() oraz Object.assign().
Szybkie przypomnienie: Jeśli chcemy połączyć dwa obiekty poprzez [[Prototype]], tak żeby jeden mógł korzystać z dobrodziejstw drugiego wystarczy taki kawałek kodu:

Używamy Object.create(), aby połączyć [[Prototype]] obiektu B z A, spójrzcie na obrazek niżej:

Obiekt B linkuje do A

I szybki dowód, że są połączone poprzez [[Prototype]].

  1. Dodaje do A jakiś atrybut „costam” i podstawiam pod niego liczbę 2.
  2. Wypisuję atrybut „costam” z B  i dostaję tą liczbę.
  3. Wyświetlam A i widzę, że ma atrybut „costam”,
  4. Wyświetlam B i co? I pewnie, że nie ma. Mamy połączenie poprzez [[Prototype]]  z A.

Object.assign()

Przyda nam się również znajomość Object.assgin() do „mergowania” obiektów. Ta funkcja zwraca obiekt będący połączeniem wszystkich innych obiektów podanych jako jej argumenty. Pierwszy argument to obiekt, który będzie tak jakby celem łączenia całej reszty –  Object.assign( target, source1, source2, … )

Spójrzmy na przykład:

To tyle w części wstęp, przejdźmy do poznania typów dziedziczenia.

Typy dziedziczenia w JavaScript.

Delegate prototype

Weźmy na pierwszy ogień Delegate prototype – (delegowanie prototypu) – tzn. możemy sami ustalić z jakim obiektem połączyć inny obiekt.

Spójrzcie znowu na przykład:

 

Tworzymy dwa obiekty –  greenAlien i redAlien. Obiekt redAlien jest połączony z greenAlien poprzez [[Prorotype]] i może korzystać z funkcji sayHello(). Następnie tworzymy dwa kolejne obiekty alienA – połączony z greenAlien i alienB połączony z redAlien. Dodatkowo ustawiam im imiona (żeby nie byli takimi anonimowymi istotami). Jak wygląda połączenie pomiędzy tymi obiektami? Spójrzcie na obrazek poniżej:

Więcej obiektów  – Factory function

Factory function to taki rodzaj delegate prototype i używamy jej zazwyczaj kiedy chcemy tworzyć więcej obiektów, które są do siebie podobne.

Czym jest Factory function?

Funkcję, która tworzy obiekty nazywamy albo konstruktorem (jeśli jest wywoływana ze słówkiem new) albo factory function (jeśli zwraca obiekty danego typu).

 

Mamy obiekt alien – taki sam jak wcześniej. Tworzymy funkcję createAlien, która zwraca nam nowy obiekt połączony za pomocą [[Prototype]] z obiektem alien  oraz rozszerzony za pomocą Object.assign o pole name. Nowy obiekt alienB nie jest w żaden sposób połączony z funkcją.

Concatenative inheritance

Kolejny typ dziedziczenia w JavaScript, który poznamy to dziedziczenie konkatenatywne  i jest to proces kopiowania właściwości z jednego obiektu do drugiego, nie zachowując odniesienia między tymi dwoma obiektami. Dostęp do właściwości jest szybszy, ponieważ kopiowane są dziedziczone właściwości, ale jeśli np. mamy jedną funkcję, z której chcą skorzystać inne obiekty to mamy ją skopiowaną do każdego z nich. Marnotrawstwo pamięci. 

Podsumowanie

Zrobiłam mały test, który polega na tym, że tworzę 1000 obiektów w różny sposób: Delegate prototype (FF) , Concatenative Inheritance (CI) oraz za pomocą konstruktora (Class). Następnie próbuje 1000 razy dostać się do funkcji, którą mają zdefiniowany w różny sposób.
Na kod można spojrzeć tutaj.

Na moim komputerze wynik wyszedł tak jak widzicie na screenie poniżej. Ale na innych systemach i przeglądarkach wyniki są inne. Wytłumaczenie mamy jedno: Różna implementacja dostępu w różnych silnikach JavaScript.

Komentarze
 

Agata Malec-Sromek

 

Dodaj komentarz