将原型链分为两类可能会有所帮助。
考虑构造函数:
function Person() {}
Object.getPrototypeOf(Person)的值是一个函数。事实上,它是Function.prototype。由于Person是作为一个函数创建的,所以它与所有函数共享相同的原型函数对象。与Person相同__proto__,但不应使用该属性。无论如何,使用Object.getPrototypeOf(Person),您可以有效地沿着所谓的原型链的阶梯前进。
向上的链条如下所示:
人员→ 功能.原型→ Object.prototype(终点)
重要的是,这个原型链与Person可以构造的对象关系不大。这些构造的对象有自己的原型链,而这个链可能和上面提到的对象没有共同的祖先。
以该对象为例:
var p = new Person();
p与Person没有直接的原型链关系。他们的关系是不同的。对象p有自己的原型链。使用Object.getPrototypeOf,您会发现链如下:
p型→ 人物原型→ Object.prototype(终点)
此链中没有函数对象(尽管可能是)。
所以Person似乎与两种链条有关,它们各自生活。要从一条链“跳”到另一条链,请使用:
.prototype:从构造函数的链跳到创建的对象的链。因此,此属性仅为函数对象定义(因为new只能用于函数)。构造函数:从创建的对象链跳到构造函数链。
以下是所涉及的两个原型链的可视化演示,以列表示:
总结如下:
prototype属性不提供主题原型链的信息,而是提供主题创建的对象的信息。
属性原型的名称会导致混淆,这并不奇怪。如果将此属性命名为prototypeOfConstructedInstance或类似的名称,可能会更清楚。
您可以在两个原型链之间来回跳转:
Person.prototype.constructor === Person
通过将不同的对象显式指定给原型属性,可以打破这种对称性(稍后将详细介绍)。
创建一个函数,获取两个对象
Person.prototype是在创建函数Person的同时创建的对象。它具有Person作为构造函数,即使该构造函数尚未实际执行。因此,同时创建了两个对象:
功能Person本身将函数作为构造函数调用时充当原型的对象
两者都是对象,但它们具有不同的角色:函数对象构造,而另一个对象表示函数将构造的任何对象的原型。原型对象将成为其原型链中构建对象的父对象。
由于函数也是一个对象,所以它在自己的原型链中也有自己的父级,但请记住这两个链是关于不同的事情的。
以下是有助于把握问题的一些等式——所有这些都是正确的:
函数Person(){};//这是构造函数(函数对象)的原型链信息:console.log(Object.getPrototypeOf(Person)==Function.prototype);//在同一层次结构中更进一步:console.log(Object.getPrototypeOf(Function.prototype)==Object.proto原型);console.log(Object.getPrototypeOf(Object.prototype)==null);console.log(Person.__proto__==Function.prototype);//这里我们交换通道,并查看构造函数的构造函数console.log(Person.constructor==函数);console.log(函数的个人实例);//Person.prototype由Person创建(创建时)//这里我们来回交换车道:console.log(Person.prototype.constructor==人员);//虽然它不是它的一个实例:console.log(!(Person.prototype instanceof Person));//实例是由构造函数创建的对象:var p=新角色();//类似于为构造函数显示的内容,这里我们有//构造函数创建的对象也是如此:console.log(Object.getPrototypeOf(p)==Person.prototype);console.log(p.__proto__==Person.prototype);//在这里,我们交换通道,并查看构造函数console.log(p.constructor==人员);console.log(p instanceof Person);
向原型链添加级别
虽然在创建构造函数函数时创建了原型对象,但可以忽略该对象,并为该构造函数创建的任何后续实例分配另一个应用作原型的对象。
例如:
function Thief() { }
var p = new Person();
Thief.prototype = p; // this determines the prototype for any new Thief objects:
var t = new Thief();
现在t的原型链比p长一步:
吨→ p→ 人物原型→ Object.prototype(终点)
另一个原型链不再长:Thief和Person是兄弟姐妹,在原型链中共享同一个父级:
个人}小偷}→ 功能.原型→ Object.prototype(终点)
之前展示的图形可以扩展到这一点(省略了最初的Thief.原型):
蓝色线条表示原型链,其他彩色线条表示其他关系:
在对象及其构造函数之间在构造函数和将用于构造对象的原型对象之间