Tracing the prototype chain using constructor.prototype

If I can use obj.constructor.prototype to access the prototype of an object, then why can't I use obj.constructor.prototype.constructor.prototype to move the prototype chain and should use Object.getPrototypeOf ?

 function MyConstructor() { this.prop = 1; } var o = new MyConstructor(); console.log(o.constructor.prototype) // MyConstructor console.log(o.constructor.prototype.constructor.prototype) // MyConstructor? 

Should I return the prototype MyConstructor, which is located in function() { [native code] } (in the Chrome console)?

+7
source share
2 answers

All constructors are instances of the global Function object:

 function Foo(){ this.x = 1 }; // Dummy constructor function console.log(Foo instanceof Function) // => true; Foo is an instance of global Function constructor 

All prototypes are instances of the global Object :

 console.log(Foo.prototype instanceof Object); // => true 

When the Foo constructor is defined, it automatically has a Foo.prototype object attached to it, which you can consider as an "empty" object, which itself, as indicated above, inherits from the global Object object. In other words, the prototype of Foo.prototype is Object.prototype :

 function Foo(){ this.x = 1 }; // Dummy constructor function console.log(Foo.prototype); // Foo (object); already exists console.log(Object.getPrototypeOf(Foo.prototype) === Object.prototype); // => true 

Since Foo.prototype is an empty object, one would expect its constructor to be the global constructor construct of Object :

 function Foo(){ this.x = 1 }; // Dummy constructor function console.log(Foo.prototype.constructor) // => function Foo() { this.x = 1; } ?? console.log(Foo.prototype.constructor === Object.prototype.constructor); // => false 

However, this "empty" object has an explicit self-referential constructor property that points to function Foo(){ this.x = 1 } and overwrites or "masks" the default constructor property that you expect:

 function Foo(){ this.x = 1 }; // Dummy constructor function delete Foo.prototype.constructor; // Delete explicit constructor property console.log(Foo.prototype.constructor) // => function Object() { [native code] } console.log(Foo.prototype.constructor === Object.prototype.constructor); // => true 

Therefore, you cannot use obj.constructor.prototype recursively to traverse the prototype chain and must rely on the Object.getPrototypeOf() method.

Here is a great visual link .

+7
source

If I can use obj.constructor.prototype to access object prototype

You cannot at all. See how this approach works:

 var proto = MyConstructor.prototype; // has an (nonenumberable) property "constructor" proto.hasOwnProperty("constructor"); // `true` // that points [back] to proto.constructor; // `function MyConstructor() {…}` 

As you can see, this is a circular structure of properties. When you do

 var o = new MyConstructor(); // and access o.constructor; // `function MyConstructor() {…}` // then it yields the value that is inherited from `proto` // as `o` doesn't have that property itself: o.hasOwnProperty("constructor"); // `false` 

But this only works for an object of type o , which inherits the constructor property from its prototype object and where it has useful value with something pointing to the prototype object. Think about

 var o = {}; o.constructor = {prototype: o}; 

Unfortunately. Access to o.constructor.prototype gives here o , and that could be any other meaningless value. The structure is actually the same as above with MyConstructor.prototype - and if you refer to proto.constructor.prototype.constructor.prototype[.constructor.prototype…] , you will get nothing but proto .

then why can't I use obj.constructor.prototype.constructor.prototype to move the prototype chain and should use Object.getPrototypeOf ?

Since you ended up in a circular structure like MyConstructor.prototype ), this constructor property is not inherited from Object.prototype . To really get the next object in a genuine prototype chain, you must use Object.getPrototypeOf .

 var o = new MyConstructor(); console.log(o.constructor.prototype) // MyConstructor 

Actually it should be MyConstructor.prototype . Sometimes the Chrome console gets confused when displaying useful headers for unnamed objects, but is not always correct.

If you get your prototype, it should give Object.prototype , and when you get the prototype of the MyConstructor function MyConstructor , it should be Function.prototype . Note that you can do the latter using MyConstructor.constructor.prototype again ...

+2
source

All Articles