Prototypy i dziedzictwo w JavaScript

Prototypy i dziedzictwo w JavaScript
Dziedziczenie jest koncepcją z programowania obiektowego, mimo że JavaScript w pełni wspiera dziedziczenie między rodzicami i dziećmi, praca jest daleka od tradycyjnego programowania obiektowego, to znaczy dlatego, że wszystko w JavaScript jest odwzorowane na prymitywnym konstruktorze konstruktorem Obiekt (Obiekt z kapitałem O) Dlatego jest również znany jako obiekt główny. Nie błędnie interpretuj ten obiekt główny za pomocą obiektu danych.

JavaScript jest często błędnie interpretowany jako OJęzyk zorientowany na bject, ale w rzeczywistości to nieprawda; JavaScript to język oparty na prototypach. Dziedziczenie w JavaScript osiąga coś, co nazywa się Prototypowe dziedziczenie. Aby to zrozumieć, najpierw musimy zapoznać się z tym, jak działa konstruktor w JavaScript, w jaki sposób obiekt jest tworzony przeciwko konstruktorowi i co to jest łańcuch prototypowy.

To jeden z zaawansowanych tematów JavaScript, a my zabierzemy Cię bardzo powoli i spróbujemy wyjaśnić każdą odrobinę informacji wraz z fragmentami, zacznijmy.

Jak działa konstruktor w JavaScript

Umownie, Konstruktorzy są specjalnymi funkcjami, które są wykonywane za każdym razem, gdy obiekt jest tworzony w stosunku do klasy; W JavaScript, każde wyrażenie funkcji jest konstruktor. Teraz, jeśli pochodzisz z trywialnego języka programowania i masz tło z programowaniem obiektowym, będziesz się zdezorientować. Dlatego staraj się nie porównywać koncepcji JavaScript z trywialnym programowaniem obiektowym.

Mimo że przybycie wersji JavaScript ES 6 to słowo kluczowe ”Klasa”Dodano do JavaScript, ale nie jest to używane do wdrożenia pojęcia dziedziczenia. W JavaScript możesz tworzyć obiekty zmapowane na funkcję, Tak - Funkcje.

Wyobraź sobie funkcję utworzoną za pomocą następującego kodu:

var person = function ()

Jak wspomniano powyżej, że każde wyrażenie funkcji jest konstruktorem, można to udowodnić za pomocą następujących linii wewnątrz funkcji:

var person = funkcja (nazwa)
Ten.Nazwa = nazwa;
Ten.Wiek = 20

Teraz, jak widać, tworzymy funkcję i wewnątrz ciała funkcji, definiujemy i inicjowujemy właściwości obiektu, tak jak robimy to w każdym normalnym konwencjonalnym konstruktorze. Teraz utwórzmy niektóre obiekty zmapowane na to Osoba Funkcja konstruktora z następującymi wierszami kodu:

var p1 = nowa osoba („John”);
var p2 = nowa osoba („Albert”);

Teraz tworzymy obiekty, ale nie mamy metody wewnątrz obiektów, które zwróci nam nazwę osoby, którą właśnie utworzyliśmy, więc stwórzmy tę funkcję w konstruktor Osoba obiekt.

var person = funkcja (nazwa)
Ten.Nazwa = nazwa;
Ten.Wiek = 20;
Ten.getName = function ()
powrót (to.nazwa)

Teraz musimy wywołać tę funkcję z każdego pojedynczego obiektu za pomocą następujących wierszy kodu:

konsola.Log (P1.getName ());
konsola.Log (p2.getName ());

Po uruchomieniu całego fragmentu otrzymujemy następujące dane wyjściowe na konsoli:

Oto główny problem z korzystaniem z tego typu szablonu, wyobraź sobie, że masz 100 obiektów Osoba, Te 100 obiektów będzie miało swoje własny 100 różnych GetName() Funkcje:

Dzieje się tak, ponieważ te obiekty są instancjami Osoba, dzięki czemu jest zbędne na pamięci. To tutaj Właściwość prototypowa wchodzi w grę.

Właściwość prototypowa

Każda funkcja i każdy obiekt ma nazwaną właściwość Prototyp, Ten prototyp zawiera metody i właściwości funkcji, a ta prototypowa właściwość jest udostępniana między wszystkimi instancją/obiektami, które są odwzorowane na funkcję, spójrz na ten fragment:

Gdybyśmy utworzyli niektóre obiekty na podstawie tej funkcji „X”, Dziedziczą metody i właściwości w„prototyp”Funkcji. W naszym przykładzie główną funkcją byłaby Osoba A obiekty są P1, P2, tak jak:

Korzystanie z właściwości prototypowej do tworzenia prototypowego dziedziczenia

Naszym głównym problemem z trywialnym podejściem było to, że każdy obiekt miał swój własny GetName() funkcje, im bardziej obiekty, tym więcej jest liczbą GetName() Funkcje w pamięci. Aby to usunąć, piszemy funkcja getName () poza wyrażeniem konstruktora i wewnątrz właściwości prototypowej za pomocą składni:

nazwa obiektu.prototyp.MethodName

Nasz kod zmienia się w:

var person = funkcja (nazwa)
Ten.Nazwa = nazwa;
Ten.Wiek = 20;

osoba.prototyp.getName = function ()
Zwróć to.nazwa;

var p1 = nowa osoba („John”);
var p2 = nowa osoba („Albert”);
konsola.Log (P1.getName ());
konsola.Log (p2.getName ());

Wyjście jest dokładnie takie samo jak ostatni raz:

Ale tym razem różnica polega na tym, że zamiast każdego obiektu mającego własny GetName() Funkcja, każdy obiekt uzyskuje dostęp do GetName() Funkcja w swoim nadrzędnym i używającą tej funkcji do wykonania podanej instrukcji. To się nazywa "Prototypowe dziedziczenie„W JavaScript. W końcu nie czyni go zbędnym w pamięci.

Obiekt główny

Wszystko w JavaScript jest zasadniczo obiektem, oznacza to, że wszystko w JavaScript opiera się Obiekt (z kapitałem o).

Aby to wyjaśnić, użyj następujących wierszy kodu i otwórz konsolę przeglądarki.

var demo = function ()

konsola.Dir (demo);

Tworzysz funkcję z pustym konstruktorem i konsola.reż() Wyświetla szczegóły próbny() Definicja funkcji na konsoli, zobaczysz to:

Rozwiń małą grot strzałki i zbadaj __proto__ właściwość tej funkcji, __proto__ Właściwość mówi nam o tym, jaki obiekt został zmapowany na tę funkcję, zobaczysz to:

Teraz stwórzmy instancję tej funkcji demo i zbadajmy jej __proto__ tak jak:

var demo = function ()

niech x = new demo ();
konsola.Dir (x);

Po uruchomieniu tego kodu należy zobaczyć następujące dane wyjściowe na konsoli:

Rozwiń to i zbadaj konstruktor, na który zmapowano instancję „X”, zobaczysz:

Co oznacza ten obiekt X ma demo rodzica i już wiemy, że Demo funkcjijest mapowany na obiekt JavaScript. To tworzy łańcuch prototypowy jako:

Obiekt "X”Może uzyskać dostęp do metod i właściwości obiektu głównego, tworząc w ten sposób łańcuch spadku.

Jeśli po raz ostatni spojrzymy w naszej konsoli, możemy zbadać, że obiekt główny ma tę jedną metodę w swojej prototypowej właściwości ToString () Jak:

I nazywamy tę właściwość na obiekcie „X”I na funkcji próbny że stworzyłeś jako:

konsola.Log (x.ToString ());
konsola.Log (demo.ToString ());

Otrzymujesz wyjście jako:

Widać, zarówno obiekt, jak i funkcja były w stanie uzyskać dostęp do tej metody, nawet jeśli nie została w nich zdefiniowana.

Tak działa dziedzictwo w JavaScript przez prototypy.

Wniosek

Dziedziczenie w JavaScript bardzo różni się od naszej konwencjonalnej definicji dziedziczenia w programowaniu obiektowym. W JavaScript osiągamy dziedzictwo za pomocą właściwości o nazwie prototyp. Nauczyłeś się, jak działa konstruktor w JavaScript, czym jest prototyp właściwość, jak wszystko w JavaScript jest obiektem, poznając się Obiekt główny. Ponadto dowiedziałeś się o prototypowym dziedziczeniu i wiązaniu prototypów, a ty byłeś w stanie uzyskać dostęp do metod i właściwości Obiekt główny używając obiekt że stworzyłeś.