Ta strona używa ciasteczek (cookies), dzięki którym nasz serwis może działać lepiej. Dowiedz się więcej OK, rozumiem

Inna metoda dziedziczenia prototypu

Tworzenie dynamicznych stron internetowych z zastosowaniem JavaScript, jQuery, Ajax. Dowiedz się jak to zrobić, znajdź rozwiązania swoich problemów.

Inna metoda dziedziczenia prototypu

Post 21.11.2017, 15:33:32

Czesc,

Trafiłem na ciekawy przykład:

Kod: Zaznacz cały
var Message = function() {};
Message.prototype.show = function() {
    throw 'Implement abstract class!!';
};


Kod: Zaznacz cały
var ErrorMessage = function() { };
ErrorMessage.prototype = new Message;
ErrorMessage.prototype.show = function() {
   do smth
};


Chciałem prosić o wyjaśnienie powyższego kodu. Czego nie rozumiem - w jaki sposób, wykonywana jest metoda show na prototypie Message (w jaki sposob jest dziedziczona), w przypadku kiedy nie zaimplementujemy metody na klasie ErrorMessage.

Co dla mnie sie nie zgadza: robiąc ErrorMessage.prototype = new Message; , prototyp klasy ErrorMessage zostaje nadpisany instancją klasy Message (uzywany new). Czyli prototypem ErrorMessagebedzie obiekt mający swój prototyp. Nie bedzie to nadpisaniem prototypu prototypem, jak jak bysmy zrobili to poprzez:

ErrorMessage.prototype = Object.create(Message.prototype).

Pozdrawiam!
whitty
Posty: 92
Dołączył(a): 12.07.2015

Re: Inna metoda dziedziczenia prototypu

Post 22.11.2017, 12:26:35

Kod: Zaznacz cały
ErrorMessage.prototype = new Message

powyższe jest "po staremu", z czasów gdy przeglądarki nie oferowały Object.create, Object.setPrototypeOf, __proto__.
W tych czasach były stosowane różne sztuczki, żeby uzyskać to co trzeba było uzyskać.

W każdym razie, obydwa wywołania

Kod: Zaznacz cały
ErrorMessage.prototype = new Message

i
Kod: Zaznacz cały
ErrorMessage.prototype = Object.create(Message.prototype)

są do siebie bardzo podobne. Jest tylko jedna różnica. Już wyjaśniam.

new Message w zasadzie robi to samo co Object.create. Tworzony jest obiekt, któremu jest ustawiony prototyp na Message.prototype.
W przypadku new Message, co dodatkowo się dzieje, to logika wewnątrz konstruktora Message, który może utworzonemu obiektowi przypisać jakieś własności itd. Żeby uniknąć tego zachowania, robiło się kiedyś takie coś. W uproszczeniu

Kod: Zaznacz cały
new Message

to to samo co
Kod: Zaznacz cały
var obj = Object.create(Message.prototype);
return Message.apply(obj, [argumenty dla konstruktora Message]);
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19664
Dołączył(a): 14.04.2002

Re: Inna metoda dziedziczenia prototypu

Post 22.11.2017, 12:47:59

Odnośnie wywołania .show(), działa to tak.
Gdy zrobisz
Kod: Zaznacz cały
var msg = new Message();
msg.show();

to dostaniesz błąd 'Implement abstract class!!'. Działa to w ten sposób. Interpreter JavaScriptu gdy napotka
Kod: Zaznacz cały
msg.show();
zacznie szukasz własności "show" na obiekcie "msg". Taka własność nie istnieje. W takim razie, kolejnym krokiem będzie szukanie własności "show" w prototypie tego obiektu. msg.__proto__.show istnieje, więc funkcja zostanie wywołana

Gdy zrobisz
Kod: Zaznacz cały
var msg = new ErrorMessage();
msg.show();

to błedu nie będzie. A bierze się to z tego samego co wyżej. Najpierw interpreter będzie szukał własności .show na msg. Nie ma takiej, bo nie została taka przypisana. To według specyfikacji, będzie dalej szukał własności "show" w prototypie. "msg" został utworzony przez new ErrorMessage, zatem jego prototypem będzie obiekt "new Message". Do tego obiektu została przypisana metoda "show" w tej linii
Kod: Zaznacz cały
ErrorMessage.prototype.show = function() {

dlatego ta metoda zostanie wywołana.
Przyjmując, że tej metody nie ma, to poszukiwania "show" w ErrorMessage.prototype też nie powiodą się, więc poszukiwania będą kontynuowane w prototypie prototypu (to jest ten łańcuch prototypów). Prototypem ErrorMessage.prototype jest obiekt, do którego dodana została własność "show" w tej linii
Kod: Zaznacz cały
Message.prototype.show = function() {
    throw 'Implement abstract class!!';
};

zatem ta metoda zostanie wywołana.
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19664
Dołączył(a): 14.04.2002

Re: Inna metoda dziedziczenia prototypu

Post 22.11.2017, 16:47:22

Dziękuję Ci za opisanie tematu Kuku!

Jednak nie do końca to złapałem. Chodzi mi o zapis:

ErrorMessage.prototype = new Message;

Ja to rozumiem tak, że prototypem zostaje instancja Message. Czyli obiekt bez własciwości innych oprócz __proto__.
Natomiast w praktyce tak sie nie dzieje. Prototype ErrorMessage wygląda jak typowy prototyp (jak by to nie brzmialo, czyli konstruktor itp). Nie rozumiem dlaczego, skoro robimy new.

Prosiłbym Cie o jeszcze kilka słów.
whitty
Posty: 92
Dołączył(a): 12.07.2015

Re: Inna metoda dziedziczenia prototypu

Post 22.11.2017, 17:24:29

Niestety ja nie rozumiem.

Prototypy to zwykłe obiekty.

new Message tworzy obiekt, który ma zaszyty prototyp Message.prototype.
Ten obiekt jest ustawiony jako prototyp dla przyszłych instancji ErrorMessage. Oznacza to, że obiekty utworzone za pomocą

Kod: Zaznacz cały
new ErrorMessage


mają powiązany ze sobą łańcuch prototypów ErrorMessage.prototype, Message.prototype, Object.prototype.

Kod: Zaznacz cały
var em = new ErrorMessage();
em
  .__proto__ // ErrorMessage.prototype
  .__proto__ // Message.prototype
  .__proto__ // Object.prototype
  .__proto__ // null


zobacz sobie wyniki console.log i komentarze https://jsfiddle.net/o3cqwxpq/
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19664
Dołączył(a): 14.04.2002

Re: Inna metoda dziedziczenia prototypu

Post 22.11.2017, 18:35:34

Dziękuję Kuku, console logi przeklikałem i już wiem o co chodzi. Po prostu dosc mocno mi nakreciły prototypy prototypow.

Bardzo pomogłeś, jak zawsze.

Pozdrawiam!
whitty
Posty: 92
Dołączył(a): 12.07.2015


Powrót do JavaScript


 


  • Podobne wątki
    Odpowiedzi
    Wyświetlone
    Ostatni post

Kto przegląda forum

Użytkownicy przeglądający ten dział: Bing [Bot], Yahoo [Bot] i 4 gości

Hosting, Domeny, SSL

Subskrypcja

Mamy 50864 zarejestrowanych użytkowników.
Najnowszy użytkownik: paulinaka


Nasi użytkownicy napisali:

  • 936286 wiadomości
  • w 246804 tematach

Najnowsze wpisy na blogu

Najnowsze artykuły

Najaktywniejsi (ostatnie 30 dni)