很多人都知道javascript是原型继承,每个构造函数都有一个prototype成员,通过它就可以把javascript的继承演义的美轮美奂了.
其实啊,光靠这一个属性是无法完成javascript的继承.
我们在代码中使用的prototype完成继承在这里就不多说了.大家可以查一下资料.
另外一个看不见的prototype成员.
每一个实例都有有一条指向原型的prototype属性,这个属性是无法被访问到的,当然也就无法被修改了,因为这是维护javascript继承的基础.
复制代码 代码如下:
//构造器声明
function Guoyansi(){ }
function GuoyansiEx(){}
//原型继承
GuoyansiEx.prototype=new Guoyansi();
//创建对象
var g1=new GuoyansiEx();
var g2=new GuoyansiEx();
上面的代码中的对象可以用下面的图来说明
二.原型的维护
一个构造器产生的实例,其constructor属性总是指向该构造器.我们暂且认为该话是对的.
复制代码 代码如下:
function Guoyansi(){ }
var obj1=new Guoyansi();
console.log(obj1.constructor===Guoyansi);//true
其实构造器本身是没有constructor这个属性的,那么这个属性是来自哪呢?
答案是:来自原型.
因此得出下面的结论
复制代码 代码如下:
obj1.constructor===Guoyansi.prototype.constructor===Guoyansi
既然我们可以通过constructor来寻找构造器.因此我们就可以进一步完善上面的图了.
复制代码 代码如下:
function GuoyansiEx(){}
GuoyansiEx.prototype=new Guoyansi();
console.log(GuoyansiEx.constructor===GuoyansiEx)//false
根据上图,上面的结果应该是true,但为什么是false呢?
现在做个分析.
GuoyansiEx的原型被Guoyansi的实例重写了,那么GuoyansiEx的原型中的constructor自然也是来自Guoyansi的实例.
而Guoyansi实例中的constructor又是来自Guoyansi.prototype.而Guoyansi.prototype没有被重写,
所以Guoyansi.prototype的constructor指向Guoyansi(构造函数);
根据以上分析得出下面的结论
复制代码 代码如下:
GuoyansiEx.constructor===Guoyansi.constructor===Guoyansi;
如果在开发过程中对于Constructor的指向要求非常精确的话,可以做如下处理.
复制代码 代码如下:
/**方法一:**/
function Guoyansi(){}
function GuoyansiEx(){}
GuoyansiEx.prototype=new Guoyansi();
GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.
复制代码 代码如下:
/**
方法二
**/
function Guoyansi(){}
function GuoyansiEx(){
this.constructor=arguments.callee;
}
GuoyansiEx.prototype=new Guoyansi();
复制代码 代码如下:
/**
方法三
**/
function Guoyansi(){}
function GuoyansiEx(){
this.constructor=GuoyansiEx;
}
GuoyansiEx.prototype=new Guoyansi();
三.看不见的原型有什么用呢?