您的位置:首页 > 其它

继承之构造器借用法

2017-08-16 09:56 176 查看
    写这篇还是因为在阅读别人用js实现flappy bird源码的时候,发现它用到了构造器借用法去实现继承,自己顺便也能学习一下这种继承方法,毕竟之前还没怎么看过继承-。-

还是用书上的例子开始介绍吧:

function Shape(id){
this.id=id;
}
Shape.prototype.name='Shape';
Shape.prototype.say=function(){
console.log(this.name+' '+this.id);
}

function Triangle(){
Shape.apply(this,arguments);
this.child=true;
}

Triangle.prototype=new Shape();
Triangle.prototype.name='Triangle';

var t=new Triangle(121);
console.log(t.name);//Triangle
console.log(t.child);//true
t.say();//Triangle 121

我们创建了一个Shape构造器函数(相当于我们的“父类”),然后创建了Triangle构造器函数(“子类”),然后我们实例了Triangle这个对象;我们发现我们的子对象中其实是没有id属性,say方法的,我们分别通过在子对象的构造器函数在调用父对象构造器时,通过apply将子对象中新建的this对象与父对象的this值绑定起来;然后通过将子对象的原型对象赋值我们父对象的实例,使得子对象可以使用父对象原型上的方法和属性,之所以实例一个对象是为了对子对象原型改变的时候不会对父对象产生影响;

有心的朋友可能注意到了我上篇写的原型陷阱,这里我们将子对象的原型全部覆盖后并没有再重置子对象原型constructor属性,是因为我们这里是继承呀~我们就是要继承父对象原型上的方法,然后我们可以再在我们的原型上添加数据就OK了,进行子对象原型方法的扩展;

这样我们就实现了构造器借用法实现继承,不过这里会存在一个问题,就是我们的父对象的构造器会被调用两次!

一次是发送在通过apply()方法继承其自身属性时,而另一次则发生在通过new Shape()这个地方;

就好比我上面的这个id属性,在t中其实是有2个,真正的来说是其构造函数Triangle有2个id,一个在其自身属性上,一个在其原型对象上;

我们打印一下:

console.log(Triangle.prototype);//Shape {id: undefined, name: "Triangle"}
console.log(t);//Triangle {id: 121, child: true}

当然我们知道当私有属性上和原型上都有同一个属性或者方法的时候会优先用私有属性上,所以我们打印t.id会是121,不会是undefined,但是这样还是不好,会造成混淆;

我们的解决办法就是将其构造函数上原型的方法使用对象复制,不new一个实例;

我们需要实现一个对象拷贝的函数:

function deepCopy(parent,child){
child=child||{};
for(var i in parent){
if(typeof parent[i]=='object'){
child[i]=Array.isArray(parent[i])?[]:{};
deepCopy(parent[i],child[i]);
}
else{
child[i]=parent[i];
}
}
return child;
}


然后将其父对象上的原型拷贝给子对象的原型

deepCopy(Shape.prototype,Triangle.prototype)

但是这个方法又有一个问题,如果我父对象在原型上再扩展的活,那么这边子对象是无法获取到父对象的新扩展方法和属性的,或者我们可以在父对象扩展的时候再对子对象进行拷贝一下,不过这次可以判断一下,重复的就不用添加了。目前就只想到这种比较笨的办法了-。-

function deepCopy(parent,child){
child=child||{};
for(var i in parent){
if(child[i]!=parent[i]){
if(typeof parent[i]=='object'){
child[i]=Array.isArray(parent[i])?[]:{};
deepCopy(parent[i],child[i]);
}
else{
child[i]=parent[i];
}
}
}
return child;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: