Как __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
Я знаю, что я не первый, кто это сделал, но было более интересно понять, что это можно найти:-). В любом случае, после этого я нашел, например. эта другая диаграмма, которая, по моему мнению, говорит примерно то же самое:
Макет объекта 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
не существует в созданных объектах, но наследуется от прототипа.
Ответ 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 __ моего объекта начнет указывать на прототип этой функции.