Javascript 使用constructor.prototype遍历原型链

Javascript 使用constructor.prototype遍历原型链,javascript,constructor,prototype,Javascript,Constructor,Prototype,如果我可以使用obj.constructor.prototype访问对象的原型,那么为什么我不能使用obj.constructor.prototype.constructor.prototype遍历原型链,并且必须使用object.getPrototypeOf function MyConstructor() { this.prop = 1; } var o = new MyConstructor(); console.log(o.constructor.prototype) //

如果我可以使用
obj.constructor.prototype
访问对象的原型,那么为什么我不能使用
obj.constructor.prototype.constructor.prototype
遍历原型链,并且必须使用
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?

它是否应该返回MyConstructor的原型,即
function(){[native code]}
(在Chrome控制台中)?

所有构造函数都是全局
函数
对象的实例:

function Foo(){ this.x = 1 }; // Dummy constructor function

console.log(Foo instanceof Function) // => true; Foo is an instance of global Function constructor
console.log(Foo.prototype instanceof Object); // => true
所有原型都是全局
对象
对象的实例:

function Foo(){ this.x = 1 }; // Dummy constructor function

console.log(Foo instanceof Function) // => true; Foo is an instance of global Function constructor
console.log(Foo.prototype instanceof Object); // => true
定义构造函数
Foo
时,它会自动附加一个
Foo.prototype
对象,您可以将其视为一个“空白”对象,如上所述,它本身从全局
对象继承。换句话说,
Foo.prototype
的原型是
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
由于
Foo.prototype
是一个空白对象,因此可以预期其构造函数是全局
对象
构造函数:

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
但是,此“空白”对象有一个显式的自引用
构造函数
属性,该属性指向
函数Foo(){this.x=1}
,并覆盖或“屏蔽”您期望的默认构造函数属性:

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
因此,您不能递归地使用
obj.constructor.prototype
遍历原型链,而必须依赖
Object.getPrototypeOf()
方法

这是一个很棒的例子

如果我可以使用obj.constructor.prototype访问对象的原型

一般来说,你不能。考虑这种方法是如何工作的:

var proto = MyConstructor.prototype;
// has an (nonenumberable) property "constructor"
proto.hasOwnProperty("constructor"); // `true`
// that points [back] to
proto.constructor; // `function MyConstructor() {…}`
如你所见,这是一个循环属性结构。当你这样做的时候

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`
但这只适用于像
o
这样的对象,它们从原型对象继承
构造函数
属性,并且具有指向原型对象的有用值。想到

var o = {};
o.constructor = {prototype: o};
哎呀。访问
o.constructor.prototype
在这里产生
o
本身,它可能是任何其他无意义的值。结构实际上与上面的
MyConstructor.prototype
-相同,如果访问
proto.constructor.prototype.constructor.prototype[.constructor.prototype…]
,那么除了
proto
之外,您不会得到任何其他内容

那么为什么我不能使用
obj.constructor.prototype.constructor.prototype
遍历原型链,而必须使用
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?
因为您被困在循环结构中,因为
MyConstructor.prototype
)本身具有
构造函数
属性,而不是从
对象.prototype
继承的。要真正获得下一个对象,即真正的原型链,必须使用
object.getPrototypeOf

实际上,它应该是MyConstructor.prototype。Chrome控制台有时在显示未命名对象的有用标题时会感到困惑,而且并不总是正确的

如果你得到它的原型,它应该产生
Object.prototype
,当你得到
MyConstructor
函数本身的原型时,它应该是
function.prototype
。请注意,您可以再次通过
MyConstructor.constructor.prototype
来完成后者