Co to znaczy, że Javascript jest językiem opartym na prototypach?


Odpowiedzi:


291

Dziedziczenie prototypowe jest formą ponownego użycia kodu obiektowego . JavaScript jest jednym z niewielu [mainstreamowych] języków obiektowych, które wykorzystują dziedziczenie prototypowe. Prawie wszystkie inne języki obiektowe są klasyczne.

W dziedziczeniu klasycznym programista zapisuje klasę, która definiuje obiekt. Z tej samej klasy można utworzyć instancję wielu obiektów, więc masz kod w jednym miejscu, który opisuje kilka obiektów w twoim programie. Klasy można następnie zorganizować w hierarchię, co przyspieszy ponowne użycie kodu. Bardziej ogólny kod jest przechowywany w klasie wyższego poziomu, z której dziedziczą klasy niższego poziomu. Oznacza to, że obiekt współdzieli kod z innymi obiektami tej samej klasy, a także z jej klasami nadrzędnymi.

W prototypowej formie dziedziczenia obiekty dziedziczą bezpośrednio od innych obiektów. Cała sprawa dotycząca zajęć odchodzi. Jeśli chcesz obiekt, po prostu napisz obiekt. Jednak ponowne użycie kodu jest nadal cenną rzeczą, więc obiekty mogą być łączone w hierarchii. W javascript każdy obiekt ma tajne łącze do obiektu, który go utworzył, tworząc łańcuch. Gdy obiekt zostanie zapytany o właściwość, której nie ma, jego obiekt nadrzędny zostanie zapytany ... ciągle w górę łańcucha, aż do znalezienia właściwości lub do osiągnięcia obiektu głównego.

Każda funkcja w JavaScript (które same są obiektami) faktycznie ma element zwany „prototypem”, który jest odpowiedzialny za dostarczanie wartości, gdy obiekt jest o nie proszony. Posiadanie tego elementu umożliwia działanie mechanizmu konstruktora (za pomocą którego obiekty są konstruowane z funkcji). Dodanie właściwości do prototypu obiektu funkcji spowoduje, że będzie on dostępny dla skonstruowanego obiektu, a także dla wszystkich obiektów, które z niego dziedziczą.

Zalety

Może nie istnieć twarda i szybka reguła, dlaczego dziedziczenie prototypów jest korzystną formą ponownego wykorzystania kodu. Ponowne użycie kodu jest korzystne, a dziedziczenie prototypowe jest rozsądnym sposobem na jego wykonanie. Można argumentować, że dziedziczenie prototypów jest dość prostym modelem ponownego wykorzystania kodu i że kod może być ponownie mocno wykorzystany w bezpośredni sposób . Ale języki klasyczne z pewnością są w stanie to osiągnąć.

Sidenote: @Andrew Hedges ma rację , że w rzeczywistości istnieje wiele języków prototypowych. Warto zauważyć, że te inne istnieją, ale warto również zauważyć, że żaden z nich nie jest zbliżony do głównego nurtu. Wydawało się, że NewtonScript ma trochę przyczepności, ale zmarł z platformą. Możliwe jest również rozszerzenie niektórych współczesnych języków w sposób, który dodaje możliwości prototypowe.


9
Cześć Kelly. Podczas gdy JavaScript jest zdecydowanie najpopularniejszym językiem prototypowym, istnieje wiele innych: en.wikipedia.org/wiki/Prototype-based_programming#Languages
Andrew Hedges

2
Cześć Andrew. Słuszna uwaga. Powinienem być bardziej dokładny. Zanotuję to.
keparo


1
+1 za świetną odpowiedź. Jeden drobny komentarz: Dla mnie klasyczne dziedzictwo wydaje się bardziej „bezpośrednie” niż prototypowe. W rzeczywistości naprawdę widzę prototypowy obiekt jako zwykłe powiązanie (z innymi obiektami), podczas gdy w skompilowanym OOP uważam klasę podstawową za „bezpośrednio odziedziczoną”. Jako takie, obiekty prototypowe są raczej powiązane ze sobą niż dziedziczone (dziedziczenie jest nieco sfałszowane). jakieś pomysły?
Więzień ZERO

3
@PrisonerZERO: Twierdziłbym, że dziedziczenie prototypów jest bardziej bezpośrednie niż klasyczne. Zamiast obiektu B wskazującego na klasę, która dziedziczy po klasie, na którą wskazuje obiekt A, wskazuje bezpośrednio na obiekt A i mówi: „Jestem taki jak ten obiekt, z wyjątkiem…”. Najważniejszą cechą dziedziczenia prototypowego i tym, co dla większości ludzi wydaje się najtrudniejsze do internalizacji, jest to, że nie odróżnia on instancji od typów. Każdy obiekt jest zarówno typem, jak i instancją. Rozróżnienia między nimi są sztuczne i celowe i zwykle są objawem utknięcia w nastawieniu klasowym.
cHao

54

Język oparty na prototypach nie rozróżnia klas na obiekty: po prostu ma obiekty. Język oparty na prototypach ma pojęcie obiektu prototypowego, obiektu używanego jako szablon, z którego można uzyskać początkowe właściwości nowego obiektu. Każdy obiekt może określać własne właściwości, zarówno podczas jego tworzenia, jak i w czasie wykonywania. Ponadto dowolny obiekt może być skojarzony jako prototyp innego obiektu , umożliwiając drugiemu obiektowi współdzielenie właściwości pierwszego obiektu.


6
Bardzo dobre wyjaśnienie, ale nieco mylące z komentarzem na temat „szablonu początkowych właściwości”. Jeśli zmienisz prototyp PO utworzeniu instancji obiektu, obiekt ten nadal otrzyma te funkcje.
nickf

32

Programowanie prototypowe to styl programowania obiektowego, w którym klasy nie są obecne, a ponowne użycie zachowania (lub dziedziczenie w językach opartych na klasach) odbywa się poprzez klonowanie istniejących obiektów, które służą jako prototypy.


Czy nadal tak się czujesz? Ponieważ jeśli tak, to jest to pierwsze wytłumaczenie, które naprawdę po prostu solidnie „kliknij” ze mną.
Chazt3n

11

Zaletą / wadą jest to, że możemy tworzyć nowe rodzaje obiektów w czasie wykonywania bez potrzeby definiowania klas (kod statyczny). Podobnie jak większość funkcji, twórcy muszą zmienić tę zaletę / wadę.

Powyżej jest możliwe, ponieważ obiekty są zasadniczo funkcjami w skrypcie Java (również zamykania).


Obiekty dynamiczne są zaletą javascript, ale tak naprawdę nie są powiązane z tym, że javascript jest językiem prototypowym lub funkcjonalnym. W wielu klasycznych językach można tworzyć obiekty dynamiczne w czasie wykonywania. Zamknięcia są również nieco niepowiązane.
keparo

2
Klasy niekoniecznie są kodem statycznym - spójrz na Python, w którym klasy same w sobie są obiektami i są zbudowane z metaklas, które również są obiektami.
Tomasz Zieliński,

6

Zamiast deklarować strukturę klasy, możesz tworzyć obiekty tego samego typu i dodawać do ich definicji w dowolnym momencie za pomocą prototypu obiektu. Jest bardziej elastyczny niż normalny sposób robienia rzeczy.


6

Jeśli po prostu użyjesz obiektów w czasie wykonywania zamiast klasy w kompilacji do budowania nowych obiektów, to otworzy możliwość rozszerzenia obiektu bez znajomości żadnych szczegółów na jego temat. Oczywiście może to szybko stać się wadą w zależności od użytkowania. Nie przyjmuję tutaj żadnych założeń dotyczących języka, więc dotyczy to języków innych niż javascript, które nie są tak dynamiczne.

myobject.prototype=unkownobject;
myobject.newproperty=1;

Możesz dostać przedmiot z dowolnego miejsca; twój własny kod, z sieci, z bazy danych, z zewnętrznego połączenia i tak dalej.

Zauważ, że język nie musi implementować dziedziczenia prototypów jak javascript. W javascript prototypowy obiekt jest po prostu współdzielony, podobnie jak jego właściwości, między spadkobiercami. Alternatywą jest skopiowanie wszystkich właściwości prototypu do nowego obiektu. Każde podejście ma swoje mocne strony w różnych sytuacjach. Jeszcze bardziej podoba mi się druga, ale nie to robi javascript.


6

Po przeczytaniu wszystkich odpowiedzi jest to wniosek

1) Dziedziczenie, w którym obiekty są dziedziczone bezpośrednio z innych obiektów

2) To nie korzysta z klas

3) Zwane także programowaniem opartym na instancjach lub bezklasowym programowaniem prototypowym

4) Ponowne użycie zachowania odbywa się poprzez klonowanie istniejących obiektów, które służą jako prototypy

5) Obiekt użyty jako szablon z nowego obiektu uzyska początkowe właściwości

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.