最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Traversing prototype chain using constructor.prototype - Stack Overflow

programmeradmin3浏览0评论

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 traverse the prototype chain and have to 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?

Shouldn't it return the prototype of MyConstructor which is function() { [native code] } (in Chrome console)?

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 traverse the prototype chain and have to 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?

Shouldn't it return the prototype of MyConstructor which is function() { [native code] } (in Chrome console)?

Share Improve this question asked Jun 30, 2013 at 20:59 user1019031user1019031 7517 silver badges16 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

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 object:

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

When a constructor Foo is defined, it automatically has a Foo.prototype object attached to it, which you can think of as a "blank" object that itself, as per the 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 a blank object, one would expect its constructor to be the global Object constructor function:

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 "blank" object has an explicit self-referential constructor property that points back to function Foo(){ this.x = 1 } and overwrites or "masks" the default constructor property you are expecting:

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 can't use obj.constructor.prototype recursively to traverse the prototype chain and have to rely on the Object.getPrototypeOf() method.

Here's a great visual reference.

If I can use obj.constructor.prototype to access the prototype of an object

You can't in general. Consider 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 see, that's a circular property structure. 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 that only works for object like o that inherit the constructor property from their prototype object and where that has a useful value with something pointing to the prototype object. Think of

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

Oops. Accessing o.constructor.prototype yields o itself here, and it could have been any other nonsensical value. The structure actually is the same as above with MyConstructor.prototype - and if you access proto.constructor.prototype.constructor.prototype[.constructor.prototype…] you won't get anything else than just proto.

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

Because you're trapped in the circular structure as MyConstructor.prototype) has that constructor property itself and not inherited from Object.prototype. For really getting the next object the true prototype chain, you have to use Object.getPrototypeOf.

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

It should have been MyConstructor.prototype actually. Chrome console sometimes gets confused at displaying useful titles for unnamed objects though, and is not always correct.

If you get its prototype, it should yield Object.prototype, and when you get the prototype of the MyConstructor function itself it should be Function.prototype. Notice that you can do the latter by MyConstructor.constructor.prototype again…

发布评论

评论列表(0)

  1. 暂无评论