当前位置:学者斋 >

设计制作 >网页设计 >

关于javascript 原型链维护和继承详解

关于javascript 原型链维护和继承详解

一.两个原型

关于javascript 原型链维护和继承详解

很多人都知道javascript是原型继承,每个构造函数都有一个prototype成员,通过它就可以把javascript的继承演义的美轮美奂了.

其实啊,光靠这一个属性是无法完成javascript的继承.

我们在代码中使用的prototype完成继承在这里就不多说了.大家可以查一下资料.

另外一个看不见的prototype成员.

每一个实例都有有一条指向原型的prototype属性,这个属性是无法被访问到的,当然也就无法被修改了,因为这是维护javascript继承的基础.

复制代码 代码如下:

//构造器声明

function Guoyansi(){ }

function GuoyansiEx(){}

//原型继承

otype=new Guoyansi();

//创建对象

var g1=new GuoyansiEx();

var g2=new GuoyansiEx();

上面的代码中的对象可以用下面的图来说明

二.原型的维护

一个构造器产生的实例,其constructor属性总是指向该构造器.我们暂且认为该话是对的.

复制代码 代码如下:

function Guoyansi(){ }

var obj1=new Guoyansi();

(tructor===Guoyansi);//true

其实构造器本身是没有constructor这个属性的,那么这个属性是来自哪呢?

答案是:来自原型.

因此得出下面的结论

复制代码 代码如下:tructor===tructor===Guoyansi

既然我们可以通过constructor来寻找构造器.因此我们就可以进一步完善上面的图了.

复制代码 代码如下:

function GuoyansiEx(){}

otype=new Guoyansi();

(tructor===GuoyansiEx)//false

根据上图,上面的结果应该是true,但为什么是false呢?

现在做个分析.

GuoyansiEx的原型被Guoyansi的实例重写了,那么GuoyansiEx的原型中的constructor自然也是来自Guoyansi的实例.

而Guoyansi实例中的constructor又是来自otype.而otype没有被重写,

所以otype的constructor指向Guoyansi(构造函数);

根据以上分析得出下面的结论

复制代码 代码如下:tructor===tructor===Guoyansi;

如果在开发过程中对于Constructor的指向要求非常精确的.话,可以做如下处理.

复制代码 代码如下:

/**方法一:**/

function Guoyansi(){}

function GuoyansiEx(){}

otype=new Guoyansi();

tructor=GuoyansiEx;//重置constructor指向.

复制代码 代码如下:

/**

方法二

**/

function Guoyansi(){}

function GuoyansiEx(){

tructor=ee;

}

otype=new Guoyansi();

复制代码 代码如下:

/**

方法三

**/

function Guoyansi(){}

function GuoyansiEx(){

tructor=GuoyansiEx;

}

otype=new Guoyansi();

三.看不见的原型有什么用呢?

看得见的原型链我们可以对他操作来完成我们的继承,那么这个看不见的原型链我们既看不见,又无法操作.要它有何用.

面向对象中继承有一个特性:相似性.子类与父类具有相似性.因此在子类中你是无法用删除从父类继承而来的成员.也就是说子类必须具有父类的特性.

为了维护这个特性,javascript在对象的内部产生了一条我们看不见的原型属性,并且不允许用户访问.这样,用户可以处于任何目的来修改constructor,

而不会破坏子类拥有父类的特性.

简而言之:内部原型是javascript的原型继承机制所需要的,而外部原型是用户实现继承所需要的.

四.火狐引擎SpiderMonkey中的__proto__

还是这段代码.

复制代码 代码如下:

function Guoyansi(){}

=24;

function GuoyansiEx(){}

var obj1=new Guoyansi();

otype=obj1;

tructor=GuoyansiEx;//重置constructor指向.

var obj2=new GuoyansiEx();

我现在想要从obj开始向上访问父类Guoyansi的prototype的属性的age.

思路是这样的.

第一步:obj2====>otype

第二部:otype===>otype;

第三部:otype===>obj1;

第四部:tructor====>Guoyansi

第五部:

写成这这样:()//24;

最终的结果是24.

最终的结果是24.可以正常执行,但是在好多书上说constructor修改后,级无法在找到父类中的原型了.不知道是怎么回事.

在火狐中提够了一种更加简洁的属性._proto_

SpiderMonkey中默认在任何创建的对象上添加了一个名为_proto_的属性,该属性指向构造器所用的原型.

其实就是我们上面提到的不可见的原型链,只不过是在这个地方变相的公开而已.

可以这样访问到age

(obj2.__proto__.__proto__);//24

这样的确是成功的访问到了父类的原型属性,但是这个属性只适用于火狐,在其他浏览器中是会出错的.

在E5中对Object做出了扩展rototypeOf(),可以访问到所有父类的原型了.

复制代码 代码如下:

function Guoyansi(){}

=24;

function GuoyansiEx(){}

var obj1=new Guoyansi();

otype=obj1;

tructor=GuoyansiEx;//重置constructor指向.

var obj2=new GuoyansiEx();

var proto=rototypeOf(obj2);

while(proto){

(tructor);

proto=rototypeOf(proto);

}

("object的原型"+proto);

结果是:GuoyansiEx

Guoyansi

Object

object的原型null

个人觉得这些应该算是javascript面向对象的精髓之一了.小伙伴们自己参考下,根据需求使用到自己的项目中去吧

  • 文章版权属于文章作者所有,转载请注明 https://xuezhezhai.com/sjzz/sjzz/pl991v.html