Как __proto__ отличается от конструктора.прототипом?

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 

Он всегда возвращает объект с рейтингом = 3.

Но если я сделаю следующее:

newtoy.__proto__.__proto__.__proto__

Цепочка заканчивается возвратом null.

Также в Internet Explorer, как бы проверить значение null, если нет свойства __proto__?

Ответ 1

Я пытался обмотать голову вокруг этого недавно и, наконец, придумал эту "карту", ​​которая, я думаю, проливает свет на этот вопрос.

http://i.stack.imgur.com/KFzI3.png enter image description here

Я знаю, что я не первый, кто это сделал, но было более интересно понять, что это можно найти:-). В любом случае, после этого я нашел, например. эта другая диаграмма, которая, по моему мнению, говорит примерно то же самое:

Макет объекта Javascript

Самое удивительное для меня было открытие того, что Object.__proto__ указывает на Function.prototype вместо Object.prototype, но я уверен, что для этого есть веская причина: -)

Я вставляю код, упомянутый в изображении здесь, а также, если кто-то хочет его протестировать. Обратите внимание, что некоторые объекты добавляются к объектам, чтобы легко узнать, где мы находимся после некоторых переходов:

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);

Ответ 2

constructor - это предопределенное свойство [[DontEnum]] объекта, на которое указывает свойство prototype объекта функции, и вначале укажет на сам объект функции.

__proto__ эквивалентен внутреннему свойству [[Prototype]] объекта, то есть его фактическому прототипу.

Когда вы создаете объект с помощью оператора new, его внутреннее свойство [[Prototype]] будет установлено на объект, на который указывает свойство конструктора prototype.

Это означает, что .constructor будет оценивать значение .__proto__.constructor, т.е. функцию-конструктор, используемую для создания объекта, и, как мы узнали, свойство protoype этой функции использовалось для установки объекта [[Prototype] ].

Отсюда следует, что .constructor.prototype.constructor идентичен .constructor (пока эти свойства не были перезаписаны); см. здесь для более подробного объяснения.

Если доступно __proto__, вы можете пройти фактическую цепочку прототипов объекта. Нет никакого способа сделать это в простой ECMAScript3, потому что JavaScript не был разработан для глубоких иерархий наследования.

Ответ 3

Прототипное наследование в JavaScript основано на свойстве __proto__ в смысле, что каждый объект наследует содержимое объекта, на которое ссылается его свойство __proto__.

Свойство prototype является специальным только для объектов Function и только при использовании оператора new для вызова конструктора Function. В этом случае созданный объект __proto__ будет установлен в конструктор Function.prototype.

Это означает, что добавление в Function.prototype автоматически отразится на всех объектах, чей __proto__ ссылается на Function.prototype.

Замена конструктора Function.prototype другим объектом будет не обновлять __proto__ свойство для любого из уже существующих объектов.

Обратите внимание, что к объекту __proto__ не следует обращаться напрямую, Object.getPrototypeOf(object) следует использовать вместо этого.

Чтобы ответить на первый вопрос, я создал набранную диаграмму ссылок __proto__ и prototype, к сожалению, stackoverflow не позволяет мне добавить изображение с "менее 10 репутацией". Может быть, в другой раз.

[Изменить] На рисунке вместо __proto__ используется [[Prototype]], потому что спецификация ECMAScript относится к внутренним объектам. Надеюсь, вы все сможете понять.

Вот несколько советов, которые помогут вам понять цифру:

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)

Обратите внимание, что свойство constructor не существует в созданных объектах, но наследуется от прототипа.

enter image description here

Ответ 4

Object - Eve, а Function - Адам, Адам (Function) использует свою кость (Function.prototype) для создания Eve (Object). Тогда кто создал Адама (Function)? - Изобретатель языка JavaScript: -).

В соответствии с ответом utsaina, я хочу добавить более полезную информацию.

Самое удивительное для меня было открытие того, что Object.__proto__указывает на Function.prototype вместо Object.prototype, но я конечно, есть веская причина для этого: -)

Это НЕ должно быть. Object.__proto__ НЕ должен указывать на Object.prototype. Вместо этого экземпляр Object o, o.__proto__ должен указывать на Object.prototype.

(Прошу прощения за использование терминов class и instance в JavaScript, но вы это знаете: -)

Я думаю, что сам класс Object является экземпляром Function, поэтому Object.__proto__ === Function.prototype. Поэтому: Object - Eve, а Function - Адам, Адам (Function) использует свою кость (Function.prototype) для создания Eve (Object).

Кроме того, даже сам класс Function является экземпляром самого Function, то есть Function.__proto__ === Function.prototype, что также почему Function === Function.constructor

Кроме того, регулярный класс Cat является экземпляром Function, то есть Cat.__proto__ === Function.prototype.

Причиной этого является, когда мы создаем класс в JavaScript, на самом деле мы просто создаем функцию, которая должна быть экземпляром Function. Object и Function являются только особыми, но они все еще являются классами, а Cat является регулярным классом.

В качестве фактора в движке JavaScript Chrome для Chrome используется следующее 4:

  • Function.prototype
  • Function.__proto__
  • Object.__proto__
  • Cat.__proto__

Все они === (абсолютно равны) другим 3, а их значение 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. Затем кто создает специальный function Empty() {} (Function.prototype)? Подумайте об этом: -)

Ответ 5

Я действительно не знаю, почему люди не исправили вас о том, где настоящая проблема в вашем понимании.

Это значительно облегчит вам задачу поиска

Итак, посмотрим, что происходит:

var newtoy = new Gadget("webcam", "black")

newtoy 
  .constructor //newtoy 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

Отлично, теперь давайте посмотрим на это __proto__

До этого, пожалуйста, запомните 2 вещи относительно __proto__:

  • Когда вы создаете объект с помощью оператора new, его внутреннее свойство [[Prototype]]/proto__ будет установлено в свойство prototype (1) его constructor function или "creator", если тебе нравится.

  • Жестко закодированный в JS -: Object.prototype.__proto__ равен null.

Ссылайтесь на эти 2 точки как "bill"

newtoy
     .__proto__ // When `newtoy` was created , Js put __proto__ value equal to the value of the cunstructor 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 a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it the `function Object(){...}`.  Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it `Object.prototype`. just remember that when Gadget.prototype was created , it 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

лучше?

Ответ 6

Каждая функция создает прототип. И когда мы создаем объект с использованием этого конструктора функций, свойство __ proto __ моего объекта начнет указывать на прототип этой функции.