function Gadget(name, color)
{
this.name = name;
this.color = color;
}
Gadget.prototype.rating = 3
var newtoy = new Gadget("webcam", "black")
newtoy.constructor.prototype.constructor.prototype.constructor.prototype
Zawsze zwraca obiekt z ratingiem = 3.
Ale jeśli wykonam następujące czynności:
newtoy.__proto__.__proto__.__proto__
Łańcuch kończy się powrotem null
.
Również w przeglądarce Internet Explorer, jak sprawdzić wartość null, jeśli nie ma __proto__
właściwości?
javascript
inheritance
prototype-programming
xdevel2000
źródło
źródło
newtoy.prototype
nie jest równynewtoy.constructor.prototype
i dlategonewtoy.constructor.prototype
nie będzie miał właściwości o nazwierating
. Podobnienewtoy.constructor.prototype.constructor.property
też nie będzie miała właściwości o nazwierating
.newtoy.constructor.prototype
będzie miała właściwość o nazwie rating. Podobnienewtoy.constructor.prototype.constructor.property
będzie mieć również właściwość o nazwie rating.__proto__
Vs.prototype
w JavaScript i jak działa JavaScript.prototype
?Odpowiedzi:
Ostatnio próbowałem to obejść i w końcu wymyśliłem tę „mapę”, która moim zdaniem rzuca pełne światło na tę sprawę
http://i.stack.imgur.com/KFzI3.png
Wiem, że nie jestem pierwszą osobą, która to wymyśliła, ale ciekawsze było wymyślenie tego niż znalezienie :-). Zresztą po tym znalazłem np. Ten kolejny schemat, który chyba mówi w zasadzie to samo:
Układ obiektów JavaScript
Najbardziej zaskakujące było dla mnie odkrycie, że zamiast tego
Object.__proto__
wskazuje , ale jestem pewien, że jest ku temu dobry powód :-)Function.prototype
Object.prototype
Wklejam kod wymieniony na obrazku tutaj, jeśli ktoś chce go przetestować. Zwróć uwagę, że do obiektów dodawane są pewne właściwości, dzięki czemu można łatwo zorientować się, gdzie jesteśmy po wykonaniu pewnych skoków:
źródło
Object.__proto__
wskazuje,Function.prototype
jest to, żeObject()
sama w sobie jest funkcją natywną, która tworzy instancję pustego obiektu. DlategoObject()
jest funkcją. Przekonasz się, że wskazują na to wszystkie inne główne__proto__
właściwości typów natywnychFunction.prototype
.Object
,Function
,String
,Number
, IArray
wszyscy dziedziczą prototyp funkcji.Object
sama jest funkcją; wynik wykonania wywoływalnegoObject
(tj. zwrócenie wartości działaniaObject()
) nie jest funkcją.constructor
jest predefiniowaną właściwością [[DontEnum]] obiektu wskazywanego przezprototype
właściwość obiektu funkcji i początkowo będzie wskazywać na sam obiekt funkcji.__proto__
jest odpowiednikiem wewnętrznej właściwości [[Prototype]] obiektu, tj. jego rzeczywistego prototypu.Kiedy tworzysz obiekt za pomocą
new
operatora, jego wewnętrzna właściwość [[Prototype]] zostanie ustawiona na obiekt wskazywany przez właściwość funkcji konstruktoraprototype
.Oznacza to, że
.constructor
zostanie oszacowana.__proto__.constructor
funkcja konstruktora użyta do utworzenia obiektu, a jak się dowiedzieliśmy,protoype
właściwość tej funkcji została użyta do ustawienia [[Prototype]] obiektu.Wynika z tego, że
.constructor.prototype.constructor
jest identyczny z.constructor
(o ile te właściwości nie zostały nadpisane); zobacz tutaj, aby uzyskać bardziej szczegółowe wyjaśnienie.Jeśli
__proto__
jest dostępny, możesz przejść przez rzeczywisty łańcuch prototypów obiektu. Nie ma sposobu, aby to zrobić w zwykłym ECMAScript3, ponieważ JavaScript nie został zaprojektowany do głębokich hierarchii dziedziczenia.źródło
.constructor.prototype
łańcuchem. Byłem też dla mnie niejasny, podczas gdy nie widziałem, że.constructor
jest równe.__proto__.constructor
. Co po prostu oznacza przechodzenie między funkcją konstruktora a jej prototypem.Dziedziczenie prototypów w JavaScript jest oparte na
__proto__
własności w tym sensie, że każdy obiekt dziedziczy zawartość obiektu, do którego odwołuje się jego__proto__
własność.prototype
Nieruchomość jest specjalny tylko dlaFunction
obiektów i wyłącznie przy użyciunew
operatora nazwaćFunction
jako konstruktora. W tym przypadku utworzony obiekt__proto__
zostanie ustawiony na obiekt konstruktoraFunction.prototype
.Oznacza to, że dodawanie do
Function.prototype
będzie automatycznie odzwierciedlać wszystkie obiekty, do których__proto__
odwołuje sięFunction.prototype
.Zastąpienie konstruktora
Function.prototype
innym obiektem nie zaktualizuje__proto__
właściwości żadnego z już istniejących obiektów.Należy pamiętać, że
__proto__
nie należy uzyskiwać bezpośredniego dostępu do właściwości , zamiast tego należy użyć Object.getPrototypeOf (object) .Aby odpowiedzieć na pierwsze pytanie, stworzyłem niestandardowy diagram
__proto__
iprototype
referencje, niestety stackoverflow nie pozwala mi na dodanie obrazu z „mniej niż 10 reputacją”. Może innym razem.[Edytuj] Rysunek używa
[[Prototype]]
zamiast,__proto__
ponieważ tak specyfikacja ECMAScript odnosi się do obiektów wewnętrznych. Mam nadzieję, że wszystko zrozumiesz.Oto kilka wskazówek, które pomogą Ci zrozumieć rysunek:
Zwróć uwagę, że
constructor
właściwość nie istnieje w utworzonych obiektach, ale jest dziedziczona z prototypu.źródło
new MyFunction()
tworzy instancję obiektu, która__proto__
powinna odwoływać się do swojego prototypu ctora, czyliMyFunction.prototype.
DlaczegoMyFunction.prototype.__proto__
odwołuje się doObject.prototype
? powinien odnosić się (podobnie jak moja pierwsza próbka) do prototypu swojego twórcy, którym jestMyFunction.prototype
(zauważcie, żeMyFunction.prototype
jest to instynktMyfunction
)Object
jest Ewa iFunction
jest Adamem, Adam (Function
) używa swojej kości (Function.prototype
) do stworzenia Ewy (Object
). Więc kto stworzył Adama (Function
)? - Wynalazca języka JavaScript :-).Zgodnie z odpowiedzią utsainy, chcę dodać więcej przydatnych informacji.
Nie powinno być.
Object.__proto__
NIE powinien wskazywaćObject.prototype
. Zamiast tego wystąpienieObject
o
,o.__proto__
powinno wskazywać naObject.prototype
.(Wybacz mi, że używam terminów
class
iinstance
JavaScript, ale wiesz o tym :-)Myślę, że
Object
sama klasa jest przykłademFunction
, dlategoObject.__proto__ === Function.prototype
. Dlatego:Object
jest Ewa iFunction
jest Adamem, Adam (Function
) używa swojej kości (Function.prototype
), aby stworzyć Ewę (Object
).Co więcej, nawet
Function
sama klasa jest instancjąFunction
samą w sobie, to znaczyFunction.__proto__ === Function.prototype
, także dlategoFunction === Function.constructor
Co więcej, zwykła klasa
Cat
jest przykłademFunction
, to znaczyCat.__proto__ === Function.prototype
.Powodem tego jest to, że kiedy tworzymy klasę w JavaScript, w rzeczywistości tworzymy funkcję, która powinna być instancją
Function
.Object
iFunction
są po prostu wyjątkowe, ale nadal są klasami, podczas gdyCat
są zwykłą klasą.W związku z tym, w silniku JavaScript Google Chrome, następujące 4:
Function.prototype
Function.__proto__
Object.__proto__
Cat.__proto__
Wszystkie są
===
(absolutnie równe) pozostałym trzem, a ich wartość wynosifunction Empty() {}
DOBRZE. Więc kto tworzy specjalny
function Empty() {}
(Function.prototype
)? Pomyśl o tym :-)źródło
function Empty() {}
odnosisz się bycie równym Function.prototype itp.? Jaki jest kod, którego użyłeś w konsoli chrome?function Empty() {}
w Google Chrome. Dodałem również wyjście konsoli._ _proto_ _
) po Function.prototype. To takie proste :)Naprawdę nie wiem, dlaczego ludzie nie poprawiali cię, gdzie jest rzeczywisty problem w twoim rozumieniu.
To znacznie ułatwiłoby wykrycie problemu
Zobaczmy więc, co się dzieje:
Świetnie, więc teraz spójrzmy na to
__proto__
Wcześniej pamiętaj o 2 rzeczach dotyczących
__proto__
:Kiedy tworzysz obiekt za pomocą
new
operatora, jego właściwość wewnętrzna[[Prototype]]
/proto__
zostanie ustawiona naprototype
właściwość (1) jegoconstructor function
lub „twórcy”, jeśli chcesz.Zakodowany na stałe w JS -:
Object.prototype.__proto__
jestnull
.Nazwijmy te 2 punkty „
bill
”Lepszy?
źródło
Każda funkcja tworzy jej prototyp. A kiedy utworzymy obiekt za pomocą tego konstruktora funkcji, wówczas właściwość __proto__ mojego obiektu zacznie wskazywać na prototyp tej funkcji.
źródło
__proto__
własność.Jeśli wszystkie te liczby były przytłaczające, spójrzmy, co oznaczają te właściwości.
STH.prototype
Podczas tworzenia nowej funkcji równolegle tworzony jest pusty obiekt połączony z funkcją
[[Prototype]]
łańcuchem. Aby uzyskać dostęp do tego obiektu, używamyprototype
właściwości funkcji.Pamiętaj, że
prototype
właściwość jest dostępna tylko dla funkcji.STH.constructor
Wspomniany powyżej obiekt prototypowy nie ma żadnych właściwości poza jedną -
constructor
. Ta właściwość reprezentuje funkcję, która utworzyła obiekt prototypowy.Tworząc
Gadget
funkcję, stworzyliśmy również obiekt podobny{constructor: Gadget}
- to nic takiegoGadget.prototype
. Jakconstructor
odnosi się do funkcji, która utworzyła prototyp obiektu,toy.constructor
reprezentujeGadget
funkcję. Piszemytoy.constructor.prototype
i{constructor: Gadget}
znowu dostajemy .Dlatego pojawia się błędne koło: możesz używać
toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype
i zawsze będzieGadget.prototype
.STH .__ proto__
Chociaż
prototype
jest właściwością specyficzną dla funkcji,__proto__
jest dostępna dla wszystkich obiektów, w jakiej się znajdujeObject.prototype
. Odnosi się do prototypu funkcji, która może stworzyć obiekt.Tutaj
toy.__proto__
jestGadget.prototype
. TakGadget.prototype
jak obiekt ({}
) i obiekty są tworzone za pomocąObject
funkcji (patrz przykład powyżej), otrzymujemyObject.prototype
. To jest wyższy obiekt w JavaScript i__proto__
może tylko wskazywaćnull
.źródło
Krótka odpowiedź:
__proto__
to odniesienie doprototype
właściwości konstruktora, który utworzył obiekt.Obiekty w JavaScript
Obiekt JavaScript jest typem wbudowanym dla zbioru zawierającego zero lub więcej właściwości. Właściwości to kontenery zawierające inne obiekty, wartości pierwotne lub funkcje.
Konstruktory w JavaScript
Funkcje są zwykłymi obiektami (które implementują się
[[Call]]
w terminach ECMA-262) z dodatkową możliwością wywoływania, ale odgrywają inną rolę w JavaScript: stają się konstruktorami ( fabrykami obiektów), jeśli zostaną wywołane przeznew
operatora. Konstruktorzy są więc przybliżonym odpowiednikiem klas w innych językach.Każda funkcja JavaScript jest w rzeczywistości instancją
Function
wbudowanego obiektu funkcji, który ma specjalną właściwość o nazwieprototype
używaną do implementacji dziedziczenia opartego na prototypach i właściwości wspólnych. Każdy obiekt utworzony przez funkcję konstruktora ma niejawne odniesienie (zwane prototypem lub__proto__
) do wartości swojego konstruktoraprototype
.Konstruktor
prototype
jest rodzajem planu budowania obiektów, ponieważ każdy obiekt utworzony przez konstruktora dziedziczy odniesienie do jegoprototype
.Łańcuch prototypów
Obiekt określa swój prototyp za pomocą właściwości wewnętrznej
[[Prototype]]
lub__proto__
. Relacja prototypów między dwoma obiektami dotyczy dziedziczenia: każdy obiekt może mieć inny obiekt jako swój prototyp. Prototyp może byćnull
wartością.Łańcuch obiektów połączonych
__proto__
właściwością nazywany jest łańcuchem prototypów . Kiedy odwołuje się do właściwości obiektu, odnosi się ono do właściwości napotkanej w pierwszym obiekcie w łańcuchu prototypów, który zawiera właściwość o tej nazwie. Łańcuch prototypów zachowuje się tak, jakby był pojedynczym obiektem.Zobacz ten obraz (pobrany z tego bloga ):
Za każdym razem, gdy próbujesz uzyskać dostęp do właściwości w obiekcie, JavaScript rozpoczyna wyszukiwanie jej w tym obiekcie i kontynuuje pracę ze swoim prototypem, prototypem prototypu i tak dalej, aż do napotkania właściwości lub jeśli
__proto__
zachowa wartośćnull
.Prawie wszystkie obiekty są instancjami
Object
, ponieważObject.prototype
są ostatnim w łańcuchu prototypów. AleObject.prototype
nie jest przykładem,Object
ponieważObject.prototype.__proto__
ma wartośćnull
.Możesz także stworzyć obiekt z
null
prototypem takim jak ten:Taki obiekt jest lepsze mapy (słownika) niż dosłownym obiektu, dlatego ten wzór jest czasami nazywany DICT wzór ( dict do słownika).
Uwaga: obiekty literalne utworzone za pomocą
{}
są instancjami,Object
ponieważ({}).__proto__
jest odwołaniem doObject.prototype
.źródło