继承之构造器借用法

    写这篇还是因为在阅读别人用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;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值