How does __proto__ differ from constructor.prototy

2018-12-31 21:24发布

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 

It always returns the object with rating = 3.

But if I do the following:

newtoy.__proto__.__proto__.__proto__

The chain ends up returning null.

Also in Internet Explorer how would I check the null if there is not a __proto__ property?

7条回答
其实,你不懂
2楼-- · 2018-12-31 21:34

Object is Eve, and Function is Adam, Adam (Function) uses his bone (Function.prototype) to create Eve (Object). Then who created Adam (Function)? -- The Inventor of the JavaScript language :-).

According to utsaina's answer, I want to add more useful info.

The most surprising thing for me was discovering that Object.__proto__ points to Function.prototype, instead of Object.prototype, but I'm sure there's a good reason for that :-)

It should NOT be. Object.__proto__ should NOT point to Object.prototype. Instead, the instance of Object o, o.__proto__ should point to Object.prototype.

(Forgive me for using the terms class and instance in JavaScript, but you know it :-)

I think the class Object itself is an instance of Function, that's why Object.__proto__ === Function.prototype. Therefore: Object is Eve, and Function is Adam, Adam (Function) uses his bone (Function.prototype) to create Eve (Object).

Furthermore, even the class Function itself is an instance of Function itself, that is Function.__proto__ === Function.prototype, that's also why Function === Function.constructor

Further furthermore, the regular class Cat is an instance of Function, that is Cat.__proto__ === Function.prototype.

The reason for the above is, when we create a class in JavaScript, actually, we are just creating a function, which should be an instance of Function. Object and Function are just special, but they are still classes, while Cat is a regular class.

As a matter of factor, in Google Chrome JavaScript engine, the following 4:

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

They are all === (absolutely equal) to the other 3, and their value is 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. Then who creates the special function Empty() {} (Function.prototype)? Think about it :-)

查看更多
孤独总比滥情好
3楼-- · 2018-12-31 21:37

If all those figures were overwhelming, let's take a look what the properties mean.

STH.prototype

When creating a new function, there is an empty object being created in parallel and linked to the function with [[Prototype]] chain. To access this object, we use prototype property of the function.

function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}

Bear in mind that prototype property is only available for functions.

STH.constructor

The prototype object mentioned above has no properties except for one - constructor. This property represents a function that created the prototype object.

var toy = new Gadget();

When creating Gadget function, we created an object like {constructor: Gadget} as well - that is nothing like Gadget.prototype. As constructor refers to a function that created an object prototype, toy.constructor represents Gadget function. We write toy.constructor.prototype and we are getting {constructor: Gadget} again.

Therefore, there's a vicious circle: you can use toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype and it always will be Gadget.prototype.

toy
.constructor    // Gadget
.prototype    // {constructor: Gadget}
.constructor    // Gadget
.prototype    // {constructor: Gadget}
// ...

STH.__proto__

While prototypeis a property specific for functions, __proto__ is available for all objects as it lays in Object.prototype. It refers to prototype of a function that can create an object.

[].__proto__ === Array.prototype
// true

({}).__proto === Object.prototype
// true

Here, toy.__proto__ is Gadget.prototype. As Gadget.prototype is an object ({}) and objects are created with Object function (see the example above), we get Object.prototype. This is the higher object in JavaScript and its __proto__ can only indicate 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
查看更多
余生请多指教
4楼-- · 2018-12-31 21:40

Every functions creates it's prototype. And when we create an object using that function constructor then the __proto__ property of my object will start pointing to the prototype of that function.

查看更多
回忆,回不去的记忆
5楼-- · 2018-12-31 21:44

The Prototypal Inheritance in JavaScript is based on __proto__ property in a sense that each object is inheriting the contents of the object referenced by its __proto__ property.

The prototype property is special only for Function objects and only when using new operator to call a Function as constructor. In this case, the created object's __proto__ will be set to constructor's Function.prototype.

This means that adding to Function.prototype will automatically reflect on all objects whose __proto__ is referencing the Function.prototype.

Replacing constructor's Function.prototype with another object will not update __proto__ property for any of the already existing objects.

Note that __proto__ property should not be accessed directly, Object.getPrototypeOf(object) should be used instead.

To answer the first question, I've created a bespoke diagram of __proto__ and prototype references, unfortunately stackoverflow does not allow me to add the image with "less than 10 reputation". Maybe some other time.

[Edit] The figure uses [[Prototype]] instead of __proto__ because that is how ECMAScript specification refers to internal objects. I hope you can figure everything out.

Here are some hints to help you understand the figure:

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)

Note that constructor property does not exist in created objects, but is inherited from the prototype.

enter image description here

查看更多
梦醉为红颜
6楼-- · 2018-12-31 21:47

constructor is a pre-defined [[DontEnum]] property of the object pointed to by the prototype property of a function object and will initially point to the function object itself.

__proto__ is equivalent to the internal [[Prototype]] property of an object, ie its actual prototype.

When you create an object with the new operator, its internal [[Prototype]] property will be set to the object pointed to by the constructor function's prototype property.

This means that .constructor will evaluate to .__proto__.constructor, ie the constructor function used to create the object, and as we have learned, the protoype property of this function was used to set the object's [[Prototype]].

It follows that .constructor.prototype.constructor is identical to .constructor (as long as these properties haven't been overwritten); see here for a more detailed explanation.

If __proto__ is available, you can walk the actual prototype chain of the object. There's no way to do this in plain ECMAScript3 because JavaScript wasn't designed for deep inheritance hierarchies.

查看更多
余生请多指教
7楼-- · 2018-12-31 21:48

I really don't know why people didn't correct you about where the actual problem in your understanding.

This would make a lot easier for you to spot the problem

So let's see what's going on :

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

Great , so now let's look at this __proto__

Before that , please remember 2 things regarding __proto__ :

  1. When you create an object with the new operator, its internal [[Prototype]]/proto__ property will be set to the prototype property(1) of its constructor function or "creator" if you like .

  2. Hard coded within JS — : Object.prototype.__proto__ is null.

Let's refer to these 2 points as "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

Better?

查看更多
登录 后发表回答