Czym różni się proto od konstruktora.prototyp?
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 zrobię co następuje:
newtoy.__proto__.__proto__.__proto__
Łańcuch kończy się powrotem null
.
Również w Internet Explorerze jak sprawdzić null, jeśli nie ma __proto__
właściwości?
8 answers
Ostatnio starałem się to ogarnąć i w końcu wymyśliłem tę "mapę", która wydaje mi się, że rzuca pełne światło na tę sprawę
Http://i.stack.imgur.com/KFzI3.png
Wiem, że nie jestem pierwszym, który to wymyśla, ale było ciekawiej dowiedzieć się, że znalezienie tego: -). W każdym razie, po tym znalazłem np. ten inny diagram, który myślę, że mówi zasadniczo to samo:
Najbardziej zaskakująca rzecz dla mnie było odkrycie, że Object.__proto__
wskazuje na Function.prototype
, zamiast Object.prototype
, ale jestem pewien, że jest ku temu dobry powód: -)
Wklejam tutaj również kod wymieniony na obrazku, jeśli ktoś chce go przetestować. Zauważ, że niektóre właściwości są dodawane do obiektów, aby ułatwić poznanie, gdzie jesteśmy po niektórych skokach:
Object.O1='';
Object.prototype.Op1='';
Function.F1 = '';
Function.prototype.Fp1 = '';
Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';
mycat = new Cat();
o = {};
// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 20:35:53
constructor
jest predefiniowaną właściwością [[DontEnum]] obiektu wskazywanego przez właściwość prototype
obiektu funkcji i początkowo będzie wskazywał na sam obiekt funkcji.
__proto__
jest odpowiednikiem wewnętrznej właściwości [[Prototype]] obiektu, czyli jego rzeczywistego prototypu.
Podczas tworzenia obiektu z operatorem new
, jego wewnętrzna właściwość [[Prototype]] zostanie ustawiona na obiekt wskazywany przez właściwość prototype
konstruktora.
Oznacza to .constructor
będzie oceniać do .__proto__.constructor
, czyli funkcji konstruktora użytej do wytworzenia obiektu, a jak się dowiedzieliśmy, właściwość protoype
tej funkcji została użyta do Ustawienia obiektu [[prototyp]].
Wynika z tego, że {[8] } jest identyczna 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ść rzeczywisty łańcuch prototypów obiektu. Nie da się tego zrobić w prostym ECMAScript3 ponieważ JavaScript nie został zaprojektowany do głębokich hierarchii dziedziczenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-28 16:48:46
Dziedziczenie prototypowe w JavaScript opiera się na właściwości __proto__
w tym sensie, że każdy obiekt dziedziczy zawartość obiektu, do którego odnosi się jego właściwość __proto__
.
Właściwość prototype
jest specjalna tylko dla obiektów Function
i tylko wtedy, gdy operator new
wywołuje Function
jako konstruktor. W tym przypadku __proto__
wytworzonego obiektu zostanie ustawione na Function.prototype
konstruktora.
Oznacza to, że dodanie do Function.prototype
automatycznie odbije się na wszystkich obiektach, których __proto__
jest odwołując się do Function.prototype
.
Zastąpienie konstruktora Function.prototype
innym obiektem spowoduje, że nie zaktualizuje właściwości__proto__
dla żadnego z już istniejących obiektów.
Zauważ, że __proto__
właściwość nie powinna być dostępna bezpośrednio, Object.zamiast tego należy użyć getPrototypeOf(object).
Aby odpowiedzieć na pierwsze pytanie, stworzyłem diagram __proto__
i prototype
odniesień, niestety stackoverflow nie pozwala mi dodać obrazka z "mniej niż 10 reputacja". Może innym razem.
[Edytuj]
Rysunek używa [[Prototype]]
zamiast __proto__
, ponieważ w ten sposób Specyfikacja ECMAScript odnosi się do obiektów wewnętrznych. Mam nadzieję, że wszystko wymyślisz.
red = JavaScript Function constructor and its prototype
violet = JavaScript Object constructor and its prototype
green = user-created objects
(first created using Object constructor or object literal {},
second using user-defined constructor function)
blue = user-defined function and its prototype
(when you create a function, two objects are created in memory:
the function and its prototype)
Zauważ, że constructor
właściwość nie istnieje w utworzonych obiektach, ale jest dziedziczona z prototypu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 13:40:42
Object
jest Ewą, a Function
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ć.Najbardziej zaskakującą rzeczą dla mnie było odkrycie, że
Object.__proto__
wskazuje naFunction.prototype
, zamiastObject.prototype
, ale jestem oczywiście, że jest ku temu dobry powód: -)
Object.__proto__
nie powinno wskazywać do Object.prototype
. Zamiast tego przykład Object
o
, o.__proto__
powinien wskazywać na Object.prototype
.
(Wybacz, że używam terminów class
i instance
w JavaScript, ale wiesz o tym : -)
Myślę, że sama klasa Object
jest instancją Function
, dlatego Object.__proto__ === Function.prototype
. Dlatego: Object
jest Ewą, a Function
jest Adamem, Adam (Function
) używa swojej Kości (Function.prototype
) do stworzenia Ewy (Object
).
Ponadto, nawet klasa Function
sama w sobie jest instancją Function
, to jest Function.__proto__ === Function.prototype
, dlatego też Function === Function.constructor
Ponadto Klasa zwykła Cat
jest instancją Function
, czyli Cat.__proto__ === Function.prototype
.
Powodem powyższego jest to, że kiedy tworzymy klasę w JavaScript, w rzeczywistości tworzymy tylko funkcję, która powinna być instancją Function
. Object
i Function
są po prostu wyjątkowe, ale nadal są klasami, podczas gdy {[30] } jest zwykłą klasą.
Jako czynnik, w Google Chrome JavaScript engine, następujące 4:
Function.prototype
Function.__proto__
Object.__proto__
Cat.__proto__
Wszystkie są ===
(absolutnie równe) pozostałym 3, a ich wartość wynosi function Empty() {}
> Function.prototype
function Empty() {}
> Function.__proto__
function Empty() {}
> Object.__proto__
function Empty() {}
> Cat.__proto__
function Empty() {}
> Function.prototype === Function.__proto__
true
> Function.__proto__ === Object.__proto__
true
> Object.__proto__ === Cat.__proto__
true
OK. To kto tworzy specjalne function Empty() {}
(Function.prototype
)? Pomyśl o tym: -)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-30 15:14:05
Naprawdę Nie wiem, dlaczego ludzie nie poprawili Cię, gdzie faktyczny problem w Twoim zrozumieniu.
To znacznie ułatwi ci dostrzeżenie problemu
Więc zobaczmy, co się dzieje:
var newtoy = new Gadget("webcam", "black")
newtoy
.constructor //newtoy's constructor function is newtoy ( the function itself)
.prototype // the function has a prototype property.( all functions has)
.constructor // constructor here is a **property** (why ? becuase you just did `prototype.constructor`... see the dot ? ) ! it is not(!) the constructor function !!! this is where your mess begins. it points back to the constructor function itself ( newtoy function)
.prototype // so again we are at line 3 of this code snippet
.constructor //same as line 4 ...
.prototype
rating = 3
Świetnie, więc teraz spójrzmy na to __proto__
Przed tym, proszę pamiętać 2 rzeczy dotyczące __proto__
:
Gdy tworzysz obiekt z operatorem
new
, jego wewnętrzny[[Prototype]]
/proto__
właściwość zostanie ustawiona naprototype
własność (1) jejconstructor function
lub "twórca", jeśli chcesz .Twardy kod w js -:
Object.prototype.__proto__
tonull
.
Potraktujmy te 2 punkty jako "bill
"
newtoy
.__proto__ // When `newtoy` was created , Js put __proto__'s value equal to the value of the cunstructor's prototype value. which is `Gadget.prototype`.
.__proto__ // Ok so now our starting point is `Gadget.prototype`. so regarding "bill" who is the constructor function now? watch out !! it's a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it's the `function Object(){...}`. Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it's `Object.prototype`. just remember that when Gadget.prototype was created , it's internal `__proto__` was refered to `Object.prototype` becuase as "bill" says :"..will be set to the `prototype` property of its `constructor function`"
.__proto__ // Ok so now our satrting point is `Object.prototype`. STOP. read bullet 2.Object.prototype.__proto__ is null by definition. when Object.prototype ( as an object) was created , they SET THE __PROTO__ AS NULL HARDCODED
Lepiej?Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-06 09:31:11
Każda funkcja tworzy swój prototyp. I kiedy tworzymy obiekt za pomocą konstruktora funkcji, wtedy __proto__ właściwość mojego obiektu zacznie wskazywać na prototyp tej funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 08:08:17
Jeśli wszystkie te liczby były przytłaczające, przyjrzyjmy się, co oznaczają te właściwości.
STH.prototype
Podczas tworzenia nowej funkcji, istnieje pusty obiekt tworzony równolegle i połączony z funkcją za pomocą łańcucha [[Prototype]]
. Aby uzyskać dostęp do tego obiektu, używamy właściwości prototype
funkcji.
function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}
należy pamiętać, że właściwość prototype
jest dostępna tylko dla funkcji.
STH.konstruktor
Prototypowy obiekt wspomniany powyżej nie ma właściwości z wyjątkiem jednego - constructor
. Właściwość ta przedstawia funkcję, która wytworzyła prototypowy obiekt.
var toy = new Gadget();
Tworząc funkcję Gadget
, stworzyliśmy również obiekt podobny do {constructor: Gadget}
- nie jest to nic podobnego do Gadget.prototype
. Ponieważ constructor
odnosi się do funkcji, która stworzyła prototyp obiektu, toy.constructor
reprezentuje Gadget
funkcję. Piszemy toy.constructor.prototype
i znowu dostajemy {constructor: Gadget}
.
Dlatego istnieje błędne koło: możesz użyć {[18] } i zawsze będzie Gadget.prototype
.
toy
.constructor // Gadget
.prototype // {constructor: Gadget}
.constructor // Gadget
.prototype // {constructor: Gadget}
// ...
STH.__ proto _ _
Podczas gdy prototype
jest właściwością specyficzną dla funkcji, __proto__
jest dostępna dla wszystkich obiektów, tak jak w Object.prototype
. Odnosi się do prototypu funkcji, która może utworzyć obiekt.
[].__proto__ === Array.prototype
// true
({}).__proto === Object.prototype
// true
Tutaj, toy.__proto__
jest Gadget.prototype
. Ponieważ Gadget.prototype
jest obiektem ({}
) i obiekty są tworzone za pomocą funkcji Object
(patrz przykład powyżej), otrzymujemy Object.prototype
. Jest to wyższy obiekt w JavaScript i jego {[21] } może wskazywać tylko null
.
toy
.__proto__ // Gadget.prototype (object looking like {constructor: Gadget})
.__proto__ // Object.prototype (topmost object in JS)
.__proto__ // null - Object.prototype is the end of any chain
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 21:19:15
Krótka odpowiedź: {[1] } jest odniesieniem do właściwości prototype
konstruktora, który utworzył obiekt.
Obiekty w JavaScript
Obiekt JavaScript jest typem wbudowanym dla kolekcji o zerowych lub więcej właściwościach. Właściwości to kontenery zawierające inne obiekty, prymitywne wartości lub funkcje.
Konstruktory w JavaScript
Funkcje są obiektami regularnymi (które implementują [[Call]]
w terminach ECMA-262) z dodatkową możliwością są wywoływalne, ale odgrywają inną rolę w JavaScript: stają się konstruktorami (dla obiektów), jeśli są wywoływane przez operator new
. Konstruktory są więc przybliżonym analogiem do klas w innych językach.
Każda funkcja JavaScript jest w rzeczywistości instancją Function
wbudowanego obiektu function, który ma specjalną właściwość o nazwie prototype
używaną do implementacji dziedziczenia opartego na prototypach i współdzielonych właściwości. Każdy obiekt utworzony przez funkcję konstruktora ma implicit odniesienie (nazywane prototypem lub __proto__
) do wartości jego konstruktora prototype
.
Konstruktor prototype
jest rodzajemplanu do budowania obiektów, ponieważ każdy obiekt utworzony przez konstruktor dziedziczy odniesienie do swojego prototype
.
Łańcuch prototypów
Obiekt określa swój prototyp za pomocą wewnętrznej właściwości [[Prototype]]
lub __proto__
. Prototypowa relacja między dwoma obiektami dotyczy dziedziczenia: każdy obiekt może mieć inny obiekt jako jego prototyp. Prototyp może być wartością null
.
Łańcuch obiektów połączonych właściwością __proto__
nazywa się łańcuchem prototypu . W przypadku odniesienia do właściwości w obiekcie jest to odniesienie 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 obrazek (wydobyty z tego blog):
Za każdym razem, gdy próbujesz uzyskać dostęp do Właściwości obiektu, JavaScript rozpoczyna jej wyszukiwanie w tym obiekcie i kontynuuje jej prototyp, prototyp prototypu itd., aż do napotkania Właściwości lub jeśli __proto__
zawiera wartość null
.
Ten typ dziedziczenia za pomocą łańcucha prototypów jest często nazywany delegacją, aby uniknąć mylenia z innymi językami używającymi klasy łańcuch.
Prawie wszystkie obiekty są instancjami Object
, ponieważ Object.prototype
jest ostatni w ich łańcuchu prototypów. Ale Object.prototype
nie jest instancją Object
, ponieważ Object.prototype.__proto__
posiada wartość null
.
Możesz również utworzyć obiekt z null
prototypem w następujący sposób:
var dict = Object.create(null);
Taki obiekt jest lepszą mapą (słownikiem) niż obiekt dosłowny, dlatego ten wzór jest czasami nazywany dict pattern (dict dla słownika).
Uwaga: literalne obiekty utworzone za pomocą {}
są instancjami Object
, ponieważ ({}).__proto__
jest odniesieniem do Object.prototype
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-01 21:44:09