js原型
原型链的根源
当一个类定义时,它就有原型对象(prototype object),原型对象必须有多个内部特定属性来表示类的特性。
prototype的作用——原型链的实现
每一个类又有一个prototype属性标识类的原型对象,该属性是静态属性,它有两个作用,一个是实现继承,一个是分享属性。所以实现继承和分享属性是原型链的组成部分。
1、实现继承
使用prototype静态属性来实现继承是通过改变[Prototype]的值来实现的([Prototype]表示该类的父类的原型对象,注意是父类的原型对象,一般使用_proto_来访问)。
例:
function Person(){} function Child(){}
它们分别有下面的内部属性
{
Prototype:Object原型对象
Class:Person [Class]表示类名
}
{
Prototype:Object原型对象
Class:Child
}
假如Person和Child是继承关系,那么就可以用下面的代码来实现:
Child.prototype=new Person();
因为Person实例也隐式包含了Person类的内部属性[Prototype],因此当执行这个赋值关系时,javascript解释引擎可以获取Person实例的[Prototype]属性值,然后改变Child的[Prototype]属性值,于是存在下列关系:
{
Prototype:Person
Class:Child
}
2、分享属性
在创建类的实例时,该实例隐式包含有对自身原型对象的引用,因此实例中也包含有[Prototype]属性。
一个类的所有属性都定义在原型对象上面,当类的实例访问一个属性时,javascript解释引擎就会去原型对象上查找属性,然后执行。
例:
function GrandFather(){ this.g1=""; this.g2=""; } function Father(){ this.p3=""; this.p4=""; } function Child(){ this.C5=""; } Father.prototype=new GrandFather(); Child.prototype=new Father();
那么在实例化GrandFather时,这个实例隐式包含有自身内部属性[Prototype]的值,该值包含有GrandFather类属性的描述;同样在实例化Father时,这个实例隐式包含有自身内部属性[Prototype]的值,该值包含有Father类属性的描述;在实例化Child时,该实例包含有自身内部属性[Prototype]的值,该值包含有Child类属性的描述。
如果Child的实例调用一个属性时,那么就会按照下面的步骤:
(1)首先查找Child是否存在指定属性,如果存在就执行,如果不存在就查找该实例包含的自身内部属性[Prototype]的值,查到原型对象是Father实例,执行下一步。
(2)查到Father是否存在指定属性,如果存在,就执行该属性,如果不存在,就查找该实例包含的内部属性[Prototype]的值,查到原型对象是GrandFather实例,执行下一步。
(3)查找GrandFather是否存在指定属性,如果存在就执行,如果不存在,就查找该实例包含的内部属性[Prototype]的值,查到原型对象是Object实例,执行下一步。
(4)查找Object是否存在该属性,如果存在就执行,如果不存在,就会返回undefined,因为Object就是原型链的尽头。
因为方法就是类型为function的属性,因此,这一过程,同样适用于方法。
总结:
每一个类都有一个prototype属性,这是一个静态属性,该属性包含了标识该类的一个对象,这个对象称为原型对象。
在原型对象上定义了一些属性用于描述该类,其中就包含了该类的基类信息,通过信息,javascript解释引擎就可以知道该类的基类,同时基类也有相同的构成,因此javascript就可以知道基类的基类,这就建立了一个链条,因为描述基类信息的内部属性是prototype,所以该链条叫原型链。
原型链的尽头是Object的原型对象,该对象的原型对象[Prototype]的值是null。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。