js 继承
ECMAScript只支持实现继承(继承实际的方法),主要依靠原型链来实现。
1、原型链
基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
示例:
function SuperType(){
this.property = true; //实例属性
}
SuperType.prototype.getSuperValue = function(){//原型方法
return this.property;
}
function SubType(){
this.subproperty = false;
}
//SubType继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue()); //true
console.log(instance.constructor); //SuperType
说明:
以上代码创建了两个类型:SuperType 和 SubType。这两个类型都有各自的属性和方法,SubType继承了SuperType,继承是通过创建SuperType的实例,并把该实例赋给SubType的prototype。实现的本质是重写了SubType原型对象,代之以一个新类型的实例。
SubType的新原型具有SuperType所有的属性和方法,同时其内部还有一个指针[[Prototype]],指向SuperType的原型,最终结果是instance指向了SubType的原型,SubType的原型又指向了SuperType的原型。
instance.constructor指向的是SuperType,这是因为原来的SubType.prototype中的constructor被重写了。(实际上不是SubType的原型的constructor属性被重写了,而是SubType的原型指向了SuperType,而这个原型的constructor属性指向的是SuperType。)
所有引用类型默认都继承了Object,这个继承也是通过原型链类实现的。所有函数的默认原型都是Object的实例,默认原型都会包含一个内部指针,指向Object.prototype。
注意:在通过原型链实现继承时,不能使用字面量对象创建原型方法,这样会重写原型链,把我们的原型链切断。
原型链的问题:(1)、包含引用类型值的原型;
(2)、创建子类型的实例时,不能向超类型的构造函数中传递参数。
2、借用构造函数
也叫伪造对象或者经典继承,基本思想是在子类型构造函数内部调用超类型构造函数。
function SuperType(name){
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
function SubType(){
//继承了SubType,同时还传递了参数
SuperType.call(this, 'Nick');
//实例属性
this.age = 12;
}
var instance1 = new SubType();
instance1.colors.push('gray');
console.log(instance1.name);
console.log(instance1.age);
var instance2 = new SubType();
console.log(instance2.colors);
借用构造函数的问题:方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的。
3、组合继承
也叫伪经典继承,基本思想是使用原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承,这样,即通过在原型上定义方法实现了函数复用,又能保证每个实例都有它自己的属性。
function SuperType(name){
this.name = name;
this.colors = ['red', 'yellow', 'blue'];
}
SuperType.prototype.sayName = function(){
return this.name;
}
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
return this.age;
}
var instance1 = new SubType('Tom', 12);
instance1.colors.push('black');
console.log(instance1.colors);//['red', 'yellow', 'blue', 'black']
console.log(instance1.sayAge());//12
console.log(instance1.sayName());//Tom
var instance2 = new SubType('Lucy',21);
console.log(instance2.colors);//['red', 'yellow', 'blue']
console.log(SubType.prototype.isPrototypeOf(instance2));//true
console.log(SuperType.prototype.isPrototypeOf(instance2));//true
组合继承是JavaScript常用的继承模式,但是也有不足。
4、寄生组合式继承
通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
//借助原型基于已有对象创建新对象(本质上讲,object()对传入的对象执行了一次浅复制)
function object(o){
function F(){}
F.prototype = o;
return new F();
}
//使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型
function inheritPrototype(SuperType, SubType){
var prototype = object(SuperType.prototype);//创建超类型原型的一个副本
prototype.constructor = SubType;//增强对象,弥补因重写原型而失去的默认的constructor属性
SubType.prototype = prototype;
}
function SuperType(name){
this.name = name;
this.colors = ['blue', 'red', 'green'];
}
SuperType.prototype.sayName = function(){
return this.name;
}
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SuperType, SubType);
SubType.prototype.sayAge = function(){
return this.age;
}
var instance = new SubType('Tom', 12);
instance.colors.push('black');
console.log(instance.colors);
delete instance.name;
console.log(instance.name);
var instance = new SubType('Lucy', 33);
console.log(instance.colors);
普遍认为寄生组合式继承是引用类型最理想的继承范式。
js 继承的更多相关文章
- js继承
js继承有5种实现方式: 继承第一种方式:对象冒充 function Parent(username){ this.username = username; this.hello = function ...
- js继承之call,apply和prototype随谈
在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...
- js继承精益求精之寄生式组合继承
一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...
- 老生常谈--Js继承小结
一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.net/stoy ...
- Js继承小结
Js继承小结 一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.n ...
- js继承实现
JS实现继承可以分为:对象冒充和原型链继承 其中对象冒充又包括:临时变量,call 和 apply 临时变量方法: function Person(name,sex){ this.name = nam ...
- js继承之借用构造函数继承
我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...
- js继承之原型链继承
面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...
- js继承的常用方法
写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...
- JS--我发现,原来你是这样的JS:面向对象编程OOP[3]--(JS继承)
一.面向对象编程(继承) 这篇博客是面向对象编程的第三篇,JS继承.继承顾名思义,就是获取父辈的各种"财产"(属性和方法). 怎么实现继承? 我们的JavaScript比较特别了, ...
随机推荐
- Windows 8 应用商店无法连接到网络的终极完美解决方案
当你看到以下几个步骤的时候,你可能会不以为然,因为你已经试过了,还是没成功,依然提示"你的电脑没有连接到Internet或者现在无法使用Windows应用商店,要使用Windows应用商店, ...
- LINQ的Intersect方法
找到两个集合中交集部分: source code: IEnumerable<int> a = new List<int>{ { }, { }, { } }; IEnumerab ...
- 分享几个原生javascript面向对象设计小游戏
一.序言 不知大家是不是和我一样,当初都有个梦想.学编程,就是想开发游戏.结果进入大学学习之后,才知道搞的是数据库应用程序开发!在此,本人就分享下业余时间做的几个小游戏吧!本打算想用winform或w ...
- 解决SqlPlus前台程序出现中文乱码的问题
在使用sqlplus的过程中,常常会遇到某一台机器在访问oracle数据库时中文显示乱码的问题,实际上这是因为客户端字符集和服务器字符集不一致导致的.在实际使用中,服务器字符集,客户端字符集和操作系统 ...
- 应用服务器和Web服务器
如上图所示,绝大部分的公司会采用Apache+tomcat集群(或jetty集群)来部署公司的Web服务, Web服务器和应用服务器关系,先介绍一下我们常说的服务器: Tomcat服务器,是运行ser ...
- Openwrt笔记-IPv6与启动顺序
之前使用了nat6方案和x3c8021x实现了校园网上网和IPv6连接:但实际使用时经常出现莫名奇妙的问题.IPv6状态要么是无法连接网络,要么是无法连接Internet:经过研究,发现大概是自启动项 ...
- 初识 PHPunit stub 模拟返回数据
这是这段时间以来结合 PHPunit 文档和大牛们的讲解,想记录下自己学习到的知识,未来参考补充,完善学到的东西 我们一般使用单测对公司业务里的代码进行测试,他会帮忙找到你的一个个小小的思考不够全面的 ...
- ssh架构简单解释和vo po解释
Struts.spring.Hibernate在各层的作用 1)struts 负责 web层. ActionFormBean 接收网页中表单提交的数据,然后通过Action 进行处理,再Forwa ...
- 两个实用的方法从Base64字符串生成RSAPublicKey及RSAPrivatekey
public static RSAPublicKey getRSAPublidKeyBybase64(String base64s) { X509EncodedKeySpec keySpec = ne ...
- java多线程之hashmap concurrenthashmap的状态同步
最近在高并发的系统中发现,concurrenthashmap除了大家熟知的避免循环期间发生ConcurrentModificationException异常外,还有重要的一点是Retrievals r ...