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相关推荐

  1. JavaScript中的继承入门

    正统的面相对象的语言都会提供extend之类的方法用于出来类的继承,但Javascript并不提供extend方法,在Javascript中使用继承需要用点技巧. Javascript中的实例的属性和 ...

  2. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript">//继承第一种方式: ...

  3. javascript中的继承方式

    javascript中的继承方式有好几种. 下面分别举例供大家参考学习: 1.function parent() { this.x=1; } function child() { var instan ...

  4. JavaScript中es5继承(call、apply)和es6继承(super)

    欢迎加入qq群(IT-程序猿-技术交流群):757345416 今天我们来研究下JavaScript中的继承: es5: //构造器函数 function Person(name,age,sex){t ...

  5. JavaScript中的继承

    在JavaScript中没有Java中的exends关键字,只能通过其他的方式来实现继承关系. 1) 对象冒充 1 function Parent(username) 2 { 3 this.usern ...

  6. 总结JavaScript中的继承

    看了<JavaScript高级程序设计>,以自己的方式总结一下继承的内容. 书中关于继承讲了6小节内容,分为原型链.借用构造函数.组合继承.原型式继承.寄生式继承及寄生组合式继承. 其他代 ...

  7. JavaScript 中的继承(读书笔记思维导图)

    继承是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.由于函数没有签名,在 ECMAScript ...

  8. JavaScript中实现继承的方法(深入学习原型链、盗用构造函数、组合继承、原型式继承、寄生式继承、寄生式组合继承)

    一.原型链 原型链的基本思想就是通过原型继承多个引用类型的属性和方法. 构造函数.原型和实例的关系:每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型. 若原型是另 ...

  9. 详细解析JavaScript中的继承(包括组合继承和寄生式继承)

    继承:相信很多学习过Java等面向对象语言的同学,都会接触过继承,它们实现继承的主要方式是接口继承和实现继承.但由于JavaScript函数没有签名,所以无法实现接口继承.ECMAScript支持实现 ...

最新文章

  1. /boor删除恢复,
  2. 软件:推荐5款职场人必备的效率神器APP
  3. python中的数组按顺序切片_python切片(获取一个子列表(数组))详解
  4. python浅复制与深复制_Python中的浅复制与深复制
  5. 【Python】之glob库介绍
  6. gmat模考_国外GMAT高分学霸们都在用什么复习资料?(模考篇)
  7. BZOJ 2406 LuoguP4194 矩阵 有上下界可行流
  8. 登陆界面输入框内加入小图标的样式
  9. 韩顺平 linux视频教程
  10. 《具体数学》部分习题解答3
  11. acwing1282. 搜索关键词(AC 自动机)
  12. Xilinx zynq zynqMP SD EMMC
  13. 高性能Java模板引擎BSL-1.0.1发布
  14. 生信学习-二代测序知乎专栏总结[转]
  15. mplayer undefined reference to `av_lzo1x_decode''render_one_glyph'
  16. 1037u支持64位linux吗,英特尔® 赛扬® 处理器 1037U
  17. Redis设计与实现——对象
  18. 利用python声音处理库librosa提取声音信号的mfcc特征及特征融合
  19. 残差网络解决什么问题详解残差网络
  20. 2018我的博客历程:你带来微笑,我有幸得到

热门文章

  1. 要闻君说:难道金山云与京东云真的要合并了吗?中国联通获准发行不超过500亿元公司债券,都用于5G 商用?用AI技术精准来找室友?...
  2. 零基础该怎么去学习3D建模
  3. 4G价格战一触即发:流量包月还是愿望
  4. 西交计算机电气,数二满分-初试441西交电气考研纯干货分享!
  5. 八卦Google 的前端开发方式及流程
  6. 泰山OFFICE技术讲座:给中文设置英文字体,会怎样
  7. 如何写好eggjs单元测试
  8. 利达调试码、调试软件
  9. 线性代数——向量究竟是什么?
  10. QQ部分文件损坏,重装多次仍然老样子