02.Javascript中的继承----Inherits
02.Javascript中的继承----Inherits
本文不再过多的阐述OOP中继承的概念,只是用原生的Javascript代码来模拟类继承(不是对象扩展)
类继承:inherits
假设有已定义好的超类(父类)SuperClass和待继承的子类SubClass,于是,可以定义如下的方法来实现类继承
inherits方法的定义
如下的这个inherits方法,其实现思想主要参考《Pro JavaScript Design Patterns》【Ross Harmes and Dustin Diaz】
/** * 这个方法用来实现类继承 * @param {function} subClass 待继承的子类 * @param {function} superClass 待被继承的父类 * @exception {Error} 参数不合法时抛出异常 */ var inherits = function(subClass,superClass){if(arguments.length !== 2){throw new Error("必须明确的指定子类和父类"); } for(var i = 0,n = arguments.length;i < n;i++){if(typeof arguments[i] !== "function"){throw new Errorr("所给的子类和父类必须都是function"); } } var F = function(){}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; };
该方法的内部会进行严格的参数合法性检查,参数必须是两个,即一个子类,一个父类;另外还要求两个参数都必须是function类型,否则抛出异常,宣告继承失败
inherits方法的使用
▲第一步
/** * 定义父类 */ var SuperClass = function(){}; SuperClass.prototype = {name : "赵先烈", talk : function(){alert("我的名字叫" + this.name); } }; /** * 这里定义子类 */ var SubClass = function(){}; //实施继承 inherits(SubClass,SuperClass); //创建子类并从调用从子类继承过来的方法 var oSub = new SubClass(); oSub.talk(); //这里输出:我的名字叫赵先烈
从程序的执行结果可以看出,这种继承方法是将父类中的全部内容(除构造器以外)拷贝到子类中来,顺利的完成了类继承。
▲第二步
/** * 这里定义父类 */ var SuperClass = function(){this.name = "赵先烈"; this.talk = function(){alert("我的名字叫" + this.name); }; }; /** * 这里定义子类 */ var SubClass = function(){//这是一个空类 }; //实施继承 inherits(SubClass,SuperClass); //创建子类对象,并调用从父类继承过来的方法 var oSub = new SubClass(); oSub.talk(); //按照继承的概念,这里应该输出:我的名字叫赵先烈
程序真正执行后,才发现发生异常了,原因:在oSub实例中不存在talk方法。不是已经通过inherits方法实现继承了么,为什么会没有这个 方法呢?探究其原因,是因为在inherits的内部,只是将SuperClass的原型链原样的拷贝给了SubClass,而不在SuperClass 原型链中的属性及方法,子类就拿不到了。
那么,既要支持第一种继承,也要能满足第二种,我们只能再次对inherits方法进行升级了,将其改为如下形式:
/** * 这个方法用来实现类继承 * @param {function} subClass 待继承的子类 * @param {function} superClass 待被继承的父类 * @exception {Error} 参数不合法时抛出异常 */ var inherits = function(subClass,superClass){if(arguments.length !== 2){throw new Error("必须明确的指定子类和父类"); } for(var i = 0,n = arguments.length;i < n;i++){if(typeof arguments[i] !== "function"){throw new Errorr("所给的子类和父类必须都是function"); } } subClass.prototype = new superClass(); subClass.prototype.constructor = subClass; };
经过这样的改动,第一步和第二步中的情况就都能顺利的正常的执行了。
▲第三步
如果在第二步的基础上,将代码中的SubClass.prototype改为如下形式:
SubClass.prototype = {walk : function(){ alert("偶也,我可以走路了哎"); }, talk : function(){alert("我的名字不叫" + this.name); }
};
再执行如下代码:
inherits(SubClass,SuperClass); var oSub = new SubClass(); oSub.talk(); //这里仍然输出:我的名字叫赵先烈 //重点在下面这句 oSub.walk(); //这里会抛出异常,告诉我们,walk方法不存在
分析这个结果,oSub.talk()的输出应该为:我的名字不叫赵先烈。并且oSub.walk()也应该有输出,程序应该正常执行才对。但是,为什么会有这样的运行结果呢?
这到底是为什么呢?相信你一定早就发现了,在inherits方法中有这样一句关键的代码:
subClass.prototype = new superClass();
这里已经告诉我们,原来,子类中的原型链已经被完全替换了,其实仔细说起来,这样做是有违继承的原则的(一般不都是子类覆盖父类么?怎么 反过来了呢)。
但是这样的问题我们始终要解决,必须让这个所谓的继承能同时满足以上三种情况都能正常执行。苦思冥想后,决定改成这样:
/** * 这个方法用来实现类继承 * @param {function} subClass 待继承的子类 * @param {function} superClass 待被继承的父类 * @exception {Error} 参数不合法时抛出异常 */ var inherits = function(subClass,superClass){if(arguments.length !== 2){throw new Error("必须明确的指定子类和父类"); } for(var i = 0,n = arguments.length;i < n;i++){if(typeof arguments[i] !== "function"){throw new Errorr("所给的子类和父类必须都是function"); } } var oSuper = new superClass(); for(var key in oSuper){if(!subClass.prototype[key]){subClass.prototype[key] = oSuper[key]; } } subClass.prototype.constructor = subClass; };
OK,通过这样的升级,再次运行上面的代码,顺利通过了。
上面这个通过两次升级的inherits方法也是目前比较稳定的版本了,在后续的文章中所指的inherits方法,就是这个了。
本文旨在共同探讨Javascript中类的继承方式,只是其中的一种模拟方式,模拟之不当,还请见谅。
欢迎提出宝贵的升级建议。
02.Javascript中的继承----Inherits相关推荐
- JavaScript中的继承入门
正统的面相对象的语言都会提供extend之类的方法用于出来类的继承,但Javascript并不提供extend方法,在Javascript中使用继承需要用点技巧. Javascript中的实例的属性和 ...
- JavaScript学习13 JavaScript中的继承
JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript">//继承第一种方式: ...
- javascript中的继承方式
javascript中的继承方式有好几种. 下面分别举例供大家参考学习: 1.function parent() { this.x=1; } function child() { var instan ...
- JavaScript中es5继承(call、apply)和es6继承(super)
欢迎加入qq群(IT-程序猿-技术交流群):757345416 今天我们来研究下JavaScript中的继承: es5: //构造器函数 function Person(name,age,sex){t ...
- JavaScript中的继承
在JavaScript中没有Java中的exends关键字,只能通过其他的方式来实现继承关系. 1) 对象冒充 1 function Parent(username) 2 { 3 this.usern ...
- 总结JavaScript中的继承
看了<JavaScript高级程序设计>,以自己的方式总结一下继承的内容. 书中关于继承讲了6小节内容,分为原型链.借用构造函数.组合继承.原型式继承.寄生式继承及寄生组合式继承. 其他代 ...
- JavaScript 中的继承(读书笔记思维导图)
继承是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.由于函数没有签名,在 ECMAScript ...
- JavaScript中实现继承的方法(深入学习原型链、盗用构造函数、组合继承、原型式继承、寄生式继承、寄生式组合继承)
一.原型链 原型链的基本思想就是通过原型继承多个引用类型的属性和方法. 构造函数.原型和实例的关系:每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型. 若原型是另 ...
- 详细解析JavaScript中的继承(包括组合继承和寄生式继承)
继承:相信很多学习过Java等面向对象语言的同学,都会接触过继承,它们实现继承的主要方式是接口继承和实现继承.但由于JavaScript函数没有签名,所以无法实现接口继承.ECMAScript支持实现 ...
最新文章
- /boor删除恢复,
- 软件:推荐5款职场人必备的效率神器APP
- python中的数组按顺序切片_python切片(获取一个子列表(数组))详解
- python浅复制与深复制_Python中的浅复制与深复制
- 【Python】之glob库介绍
- gmat模考_国外GMAT高分学霸们都在用什么复习资料?(模考篇)
- BZOJ 2406 LuoguP4194 矩阵 有上下界可行流
- 登陆界面输入框内加入小图标的样式
- 韩顺平 linux视频教程
- 《具体数学》部分习题解答3
- acwing1282. 搜索关键词(AC 自动机)
- Xilinx zynq zynqMP SD EMMC
- 高性能Java模板引擎BSL-1.0.1发布
- 生信学习-二代测序知乎专栏总结[转]
- mplayer undefined reference to `av_lzo1x_decode''render_one_glyph'
- 1037u支持64位linux吗,英特尔® 赛扬® 处理器 1037U
- Redis设计与实现——对象
- 利用python声音处理库librosa提取声音信号的mfcc特征及特征融合
- 残差网络解决什么问题详解残差网络
- 2018我的博客历程:你带来微笑,我有幸得到