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?

Author: BlueEyesWhiteDragon, 2009-03-16

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 Tutaj wpisz opis obrazka

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:

Javascript object layout

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);
 213
Author: drodsou,
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.

 68
Author: Christoph,
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.

Oto kilka wskazówek, które pomogą Ci zrozumieć figurę:]}
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.

Tutaj wpisz opis obrazka

 30
Author: xorcus,
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.

Najbardziej zaskakującą rzeczą dla mnie było odkrycie, że Object.__proto__ wskazuje na Function.prototype, zamiast Object.prototype, ale jestem oczywiście, że jest ku temu dobry powód: -)

Nie powinno być. 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: -)
 15
Author: Peter Lee,
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__:

  1. Gdy tworzysz obiekt z operatorem new, jego wewnętrzny [[Prototype]]/proto__ właściwość zostanie ustawiona na prototype własność (1) jej constructor function lub "twórca", jeśli chcesz .

  2. Twardy kod w js -: Object.prototype.__proto__ to null.

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?
 7
Author: Royi Namir,
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.

 2
Author: Apoorv Nag,
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
 2
Author: Damian Czapiewski,
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):

proto.. jpg

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.

 2
Author: explogx,
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