继承之构造器借用法
2017-08-16 09:56
176 查看
写这篇还是因为在阅读别人用js实现flappy bird源码的时候,发现它用到了构造器借用法去实现继承,自己顺便也能学习一下这种继承方法,毕竟之前还没怎么看过继承-。-
还是用书上的例子开始介绍吧:
我们创建了一个Shape构造器函数(相当于我们的“父类”),然后创建了Triangle构造器函数(“子类”),然后我们实例了Triangle这个对象;我们发现我们的子对象中其实是没有id属性,say方法的,我们分别通过在子对象的构造器函数在调用父对象构造器时,通过apply将子对象中新建的this对象与父对象的this值绑定起来;然后通过将子对象的原型对象赋值我们父对象的实例,使得子对象可以使用父对象原型上的方法和属性,之所以实例一个对象是为了对子对象原型改变的时候不会对父对象产生影响;
有心的朋友可能注意到了我上篇写的原型陷阱,这里我们将子对象的原型全部覆盖后并没有再重置子对象原型constructor属性,是因为我们这里是继承呀~我们就是要继承父对象原型上的方法,然后我们可以再在我们的原型上添加数据就OK了,进行子对象原型方法的扩展;
这样我们就实现了构造器借用法实现继承,不过这里会存在一个问题,就是我们的父对象的构造器会被调用两次!
一次是发送在通过apply()方法继承其自身属性时,而另一次则发生在通过new Shape()这个地方;
就好比我上面的这个id属性,在t中其实是有2个,真正的来说是其构造函数Triangle有2个id,一个在其自身属性上,一个在其原型对象上;
我们打印一下:
当然我们知道当私有属性上和原型上都有同一个属性或者方法的时候会优先用私有属性上,所以我们打印t.id会是121,不会是undefined,但是这样还是不好,会造成混淆;
我们的解决办法就是将其构造函数上原型的方法使用对象复制,不new一个实例;
我们需要实现一个对象拷贝的函数:
然后将其父对象上的原型拷贝给子对象的原型
但是这个方法又有一个问题,如果我父对象在原型上再扩展的活,那么这边子对象是无法获取到父对象的新扩展方法和属性的,或者我们可以在父对象扩展的时候再对子对象进行拷贝一下,不过这次可以判断一下,重复的就不用添加了。目前就只想到这种比较笨的办法了-。-
还是用书上的例子开始介绍吧:
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; }
相关文章推荐
- JavaScript面向对象(4)——最佳继承模式(深拷贝、多重继承、构造器借用、组合寄生式继承)
- OC:继承、初始化方法、便利构造器
- Java 面向对象:继承,构造器参数super()
- 继承 构造器和析构器
- OC03 继承、初始化方法、便利构造器-1
- 继承树的构造器调用顺序
- 浅谈js函数继承模式之二:借用模式
- java继承中的构造器调用
- JAVA基础学习---- 继承与合成(构造器)
- OC第三天-继承,初始化方法,便利构造器 ,self,super,方法重写
- JavaScript 继承---借用构造函数
- javascript继承(二)借用构造函数的方式继承(类继承)
- javascript中的继承-借用构造函数
- OC基础 便利构造器 继承,
- 构造器的继承
- 【学习ios之路:Objective-C】继承,便利构造器.NSString应用
- swift中构造器的继承和重写
- JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
- javascript类式继承模式#2——借用构造函数
- 为什么构造器,不能被继承?