javascript中的继承-寄生组合式继承
前文说过,组合继承是javascript最常用的继承模式,不过,它也有自己的不足:组合继承无论在什么情况下,都会调用两次父类构造函数,一次是在创建子类原型的时候,另一次是在子类构造函数内部.子类最终会包含父类对象的全部实例属性,但我们不得不在调用子类构造函数时重写这些属性.请再看一次组合继承的例子:
function SuperType(name){
this.name=name;
this.friends=["gay1","gay2"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
};
funciton SubType(name,age){
SuperType.call(this,name); //第二次调用SuperType();
this.age=age;
}
SubType.prototype=new SuperType(); //第一次调用SuperType()
SubType.prototype.sayAge=function(){
alert(this.age);
};
在第一次调用SuperType构造函数时,SubType.prototype会得到两个属性:name和friends,他们都是SuperType的实例属性.只不过现在位于SubType的原型中.当调用SubType构造函数时,又会调用一次SuperType构造函数,这一次又在新对象上创建了实例属性name和friends.于是,这两个属性就屏蔽了原型中的两个同名属性.
结果是,有两组name和friends属性,一组在SubType的实例上,一组在SubType的原型上.这就是调用两次SuperType构造函数的结果.而现在,找到了解决这个问题的方法:寄生组合式继承.
寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法.思路:不必为了指定子类的原型而调用父类的构造函数,我们所需要的无非就是父类原型的一个副本而已.本质上,就是使用寄生式继承来继承父类的原型,然后在将结果指定给子类的原型:
function inheritPrototype(subType,superType){
var prototype=object(superType.prototype); //创建父类原型的一个副本 等同于使用Object.create(superType.prototype)
prototype.constructor=subType; //为副本添加constructor属性,弥补重写原型而失去的constructor属性
subType.prototype=prototype; //将创建的对象(副本)赋值给子类的原型
}
这样,我们就可以通过调用inheritPrototype()函数,替换前面例子中为子类原型的赋值语句了:
function inheritPrototype(subType,superType){
var prototype=Object.create(superType.prototype); //创建父类原型的一个副本 等同于使用Object.create(superType.prototype)
prototype.constructor=subType; //为副本添加constructor属性,弥补重写原型而失去的constructor属性
subType.prototype=prototype; //将创建的对象(副本)赋值给子类的原型
}
function SuperType(name){
this.name=name;
this.friends=["gay1","gay2"];
}
SuperType.prototype.sayName=function(){
alert(this.name);
};
function SubType(name,age){
SuperType.call(this,name); //继承SuperType
this.age=age; //扩展出age属性
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge=function(){
alert(this.age);
};//扩展出sayAge方法 var person1=new SubType("nUll",25);
var person2=new SubType("mywei",25);
person1.friends.push("gay3");
person1.sayName();
person1.sayAge();
alert(person1.friends); //gay1,gay2,gay3
alert(person2.friends); //gay1,gay2
alert(person1 instanceof SubType); //true
alert(person1 instanceof SuperType); //true
alert(SubType.prototype.isPrototypeOf(person1)); //true
alert(SuperType.prototype.isPrototypeOf(person1)); //true
这个例子的高效率体现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上创建不必要的 多余的属性.与此同时,原型链还能保持不变.因此,还能够正常使用instanceof 和isPrototypeOf确定继承关系.
YUI的YAHOO.lang.extend()方法采用了寄生组合式继承。
javascript中的继承-寄生组合式继承的更多相关文章
- JavaScript高级程序设计之寄生组合式继承
在继承中常会出现两个问题: 父类的属性变成了子类的原型 构造器指向混乱 寄生组合式继承解决了这样的问题: 属性继承到属性 原型继承到原型 构造器指向明确 // 父类 var Super = funct ...
- JavaScript对寄生组合式继承的理解
有关JavaScript的几种继承方式请移步JavaScript的几种继承方式 原型链的缺陷 SubType.prototype = new SuperType(); 这样做的话,SuperType构 ...
- JavaScript寄生组合式继承分析
JavaScript寄生组合式继承特点: 避免了在子类prototype上创建不必要多余的属性,相比直接继承基类的实例效率要高. 是JavaScript 实现继承的最有效方式. <script& ...
- JavaScript继承基础讲解,原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承
说好的讲解JavaScript继承,可是迟迟到现在讲解.废话不多说,直接进入正题. 既然你想了解继承,证明你对JavaScript面向对象已经有一定的了解,如还有什么不理解的可以参考<面向对象J ...
- 详解js中的寄生组合式继承
寄生组合式继承是js中最理想的继承方式, 最大限度的节省了内存空间. js中的寄生组合式继承要求是: 1.子对象有父对象属性的副本, 且这些不应该保存在子对象的prototype上. 2. ...
- javaScript设计模式之面向对象编程(object-oriented programming,OOP)--寄生组合式继承
组合式继承:将类式继承同构造函数继承组合使用,但是存在一个问题,子类不是父类的实例,而子类的原型式父类的实例,所以才有了寄生组合式继承. 意思就是说,寄生就是寄生式继承,寄生式继承就是依托于原型继承, ...
- Javascript继承6:终极继承者----寄生组合式继承
/* * 寄生式继承依托于原型继承,原型继承又与类式继承想象. * 即: 原型与构造函数的组合继承 * 寄生式继承 继承原型 * 传递参数 childClass 子类 * 传递参数 parentCla ...
- js组合继承和寄生组合式继承比较
本文是原创文章,如需转载,请注明文章出处 1.js中实现组合继承(B继承A): function A(name){ this.name = name; this.ary = ["AA&quo ...
- [js高手之路]寄生组合式继承的优势
在之前javascript面向对象系列的文章里面,我们已经探讨了组合继承和寄生继承,回顾下组合继承: function Person( uName ){ this.skills = [ 'php', ...
随机推荐
- winform 异步更新ui
http://download.csdn.net/download/mingge38/9378852
- k8s安装报错 Error: unknown flag: --experimental-upload-certs
今天安装k8sV1.16的版本时候,执行突然发现命令不对,之前安装V1.15的时候是可以的,可能是版本升级的原因. 解决: unknown flag: --experimental-upload-ce ...
- pycharm问题集锦
1.pycharm的激活方式 参考博客https://blog.csdn.net/u014044812/article/details/78727496 2.总是出现波浪线,如下问题 问题原因:knn ...
- springboot(五).如何在springboot项目中使用拦截器
在每个项目中,拦截器都是我们经常会去使用的东西,基本上任一一个项目都缺不了拦截器的使用. 如日志记录.登录验证,session验证等,都需要拦截器来拦截URL请求,那springboot中的拦截器是如 ...
- Spring Cloud架构教程 (一)Hystrix监控面板
下面我们基于之前的示例来结合Hystrix Dashboard实现Hystrix指标数据的可视化面板,这里我们将用到下之前实现的几个应用,包括: eureka-server:服务注册中心 eureka ...
- beforeRouterEnter与replace的使用
这次使用beforeRouterEnter来判断是一定条件下才执行相应的页面跳转. beforeRouterEnter:组件内路由,跟data,methods同级 beforeRouteEnter ( ...
- C# 异步编程,async与await的简单学习
前提声明:C# 5.0 .NET Framework 4.5 2012-08-15 异步和等待(async和await).调用方信息(Caller Information) (C#版本与.NET版本 ...
- sqli-labs(24)
0x1 前言 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 .二次注入不是注入两次的意思,请不要混淆 0x2 什么是二阶注入 二阶注入是指客通过构造数据的形式,在浏览器或者 ...
- sqli-labs(22)
接下里我们进入第二二关 好像和第21关一样 cookie的base64加密注入 闭合变成了双引号而已 0X01 构造语句进行尝试 " union select 1,2,3# IiB1bmlv ...
- 微信 JS-SDK 各种问题记录
在开发微信公众号网页中,使用微信的 JS-SDK 会遇到各种坑.记录遇到的坑及解决方法. 1.JS-SDK 配置(url 指向). 在 JS-SDK 配置中,配置的签名基本在服务器完成,网上有各种方法 ...