用JavaScript实现单继承和多继承的简单方法


Posted in Javascript onMarch 29, 2009

JavaScript就其本质是函数式编程语言,是Lisp的后代,同时又加入了一下面向对象编程的元素,放弃了一些难懂的函数式语言的元素。

函数式编程语言可以实现面向对象编程,这是毫无疑义的,Curry方法可以实现对类和对象的模拟。但是JavaScript提供了另一种实现OOP的方法:原型继承。

因此,JavaScript实现面向对象编程和一般的函数式编程语言还是有所区别的。

本文我将会给大家介绍JavaScript实现单继承和多继承的方法。

用原型实现单继承:
有很多JavaScript库提供了一些函数帮助实现单继承。但实际上,JavaScript本身就提供了原型继承的方法。因此,根本不需要提供特定的方法来实现,简单使用JavaScript代码就可以实现单继承。

但是,JavaScript提供的原型继承方法很容易犯错,下面我给大家演示一下怎样简洁明了地实现原型继承。

假设MyB继承MyA类,那么,代码如下:

function MyA(){

if(MyA.prototype.baseClass!==undefined){

MyA.prototype.baseClass.call(this);

}

……一般代码

}

function MyB(){

if(MyB.prototype.baseClass!==undefined){

MyB.prototype.baseClass.call(this);

}

……一般代码

}

MyB.prototype=new MyA();

MyB.prototype.baseClass=MyB.prototype.constructor;//使用baseClass引用//基类的构造器函数。

MyB.prototype.constructor=MyB;//恢复子类的构造器属性 用于未来通过这个属性判//断对象的类型。

var myA=new MyA();

var myB=new MyB();

上述javascript代码中,我在每一个构造函数中都添加了这么一段代码:

if(ClassName.prototype.baseClass!==undefined){

ClassName.prototype.baseClass.call(this);

}

这段代码寻找原型中的baseClass方法,如果有,就调用它。

在后面的原型继承的实现中,我为子类创建了baseClass属性,它的值是基类的构造函数。因此,只要遵守我的方式编写代码,就可以保证基类的构造函数在子类构造实例时会得到执行。

现在,如果MyA类又继承了Base类,只需要添加3行原型继承代码即可:

MyA.prototype=new Base();

MyA.prototype.baseClass= MyA.prototype.constructor;//使用baseClass引用//基类的构造器函数。

MyA.prototype.constructor= MyA;//恢复子类的构造器属性 用于未来通过这个属性判//断对象的类型。

不需要修改MyA类本身的代码,MyA类及其子类MyB类的实例就都可以得到正确的执行。

那些JavaScript库实现的继承,需要修改Object,Function等基类,容易引起冲突。还有一些方法,每一次实现继承,都必须手工修改子类的构造函数,以使构造函数能够正确调用基类的构造函数。

上面提供的方法编写JavaScript代码很好地解决了这些问题。

用Mixin(混入)实现多继承
JavaScript本身并没有提供多继承的机制,但我们可以使用Mixin(混入)这种技巧实现多继承的效果。

下面是我编写的Mixin助手方法,可以为类和对象动态添加属性。

1,copyClassPrototypeProperties复制类的原型属性
/**

* 把源类原型上的所有属性复制到目标对象上,第一个参数是boolean值,表示是否覆盖目标类的原型的属性

*/

function copyClassPrototypeProperties(isOverride,receivingClass,givingClass){

if(arguments.length>3){

for(var i=3;i<arguments.length;i++){

receivingClass.prototype[arguments[i]]=givingClass.prototype[arguments[i]];

}

}else if(arguments.length==3){

for(var name in givingClass.prototype){

if(isOverride){

receivingClass.prototype[name]=givingClass.prototype[name];

}else{

//不覆盖

if(!receivingClass.prototype[name]){

receivingClass.prototype[name]=givingClass.prototype[name];

}

}
}

}else{

throw "Please give 3 arguments at least!";

}
}

2,copyObjectProperties复制对象的属性
/*

* 把源对象的所有属性复制到目标对象上,第一个参数是boolean值,表示是否覆盖目标对象的属性

*/

function copyObjectProperties(isOverride,receivingObject,givingObject){

if(arguments.length>3){

for(var i=3;i<arguments.length;i++){

receivingObject[arguments[i]]=givingObject[arguments[i]];

}

}else if(arguments.length==3){

for(var name in givingObject){

if(isOverride){

receivingObject[name]=givingObject[name];

}else{

//不覆盖

if(!receivingObject[name]){

receivingObject[name]=givingObject[name];

}

}
}

}else{

throw "Please give 3 arguments at least!";
}
}

3,copyProperties复制属性到对象
/*

* 把属性复制到目标对象中,属性可以有任意多个,并且可以是数组。

*/

function copyProperties(target){

for (var i=1;i<arguments.length;i++){

if(arguments[i].constructor===Array){

copyArrayProperties(target,arguments[i]);

}else{

for(var name in arguments[i]){

target[name] =arguments[i][name];

}
}
}
}
/*

* 把数组格式的属性复制到目标对象中,用户不应该直接调用这个方法

*/

function copyArrayProperties(target,arrayArg){

for(var i=0;i<arrayArg.length;i++){
if(arrayArg[i].constructor===Array){
copyArrayProperties(target,arrayArg[i]);

}else{
for(var name in arrayArg[i]){
target[name] =arrayArg[i][name];
}
}
}
}
PS:目前我正打算写一个JavaScript库,用简洁的代码提供很多功能,包括UI组件。

Javascript 相关文章推荐
JavaScript 学习 - 提高篇
Feb 02 Javascript
淘宝搜索框效果实现分析
Mar 05 Javascript
关于jQuery对象数据缓存Cache原理以及jQuery.data详解
Apr 07 Javascript
javascript去掉前后空格的实例
Nov 07 Javascript
javascript 密码框防止用户粘贴和复制的实现代码
Feb 17 Javascript
对layui中table组件工具栏的使用详解
Sep 19 Javascript
layui prompt 设置允许空白提交的方法
Sep 24 Javascript
JQuery样式与属性设置方法分析
Dec 07 jQuery
微信小程序如何实现点击图片放大功能
Jan 21 Javascript
vue学习笔记之slot插槽基本用法实例分析
Feb 01 Javascript
js利用拖放实现添加删除
Aug 27 Javascript
React实现todolist功能
Dec 28 Javascript
javascript 极速 隐藏/显示万行表格列只需 60毫秒
Mar 28 #Javascript
一个tab标签切换效果代码
Mar 27 #Javascript
js onpropertychange输入框 事件获取属性
Mar 26 #Javascript
input 高级限制级用法
Mar 26 #Javascript
HTML代码中标签的全部属性 中文注释说明
Mar 26 #Javascript
JS 常用校验函数
Mar 26 #Javascript
js 动态添加标签(新增一行,其实很简单,就是几个函数的应用)
Mar 26 #Javascript
You might like
构建简单的Webmail系统
2006/10/09 PHP
php 团购折扣计算公式
2011/11/24 PHP
PHP基于Redis消息队列实现发布微博的方法
2017/05/03 PHP
PHP检查文件是否存在,不存在自动创建及读取文件内容操作示例
2020/01/23 PHP
判断页面是关闭还是刷新的js代码
2007/01/28 Javascript
基于jquery自定义图片热区效果
2012/07/21 Javascript
js给onclick赋值传参数的两种方法
2013/11/25 Javascript
jquery的ajax跨域请求原理和示例
2014/05/08 Javascript
javascript随机之洗牌算法深入分析
2014/06/07 Javascript
Jquery焦点图实例代码
2014/11/25 Javascript
JavaScript学习笔记之Function对象
2015/01/22 Javascript
浅谈jQuery中的事件
2015/03/23 Javascript
JS 对象属性相关(检查属性、枚举属性等)
2015/04/05 Javascript
延时加载JavaScript代码提高速度
2015/12/27 Javascript
详解jQuery中的deferred对象的使用(一)
2016/05/27 Javascript
JavaScript中的return布尔值的用法和原理解析
2017/08/14 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
2018/12/28 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
JavaScript回调函数callback用法解析
2020/01/14 Javascript
vue.js实现双击放大预览功能
2020/06/23 Javascript
jquery实现点击左右按钮切换图片
2021/01/27 jQuery
python list中append()与extend()用法分享
2013/03/24 Python
python3读取MySQL-Front的MYSQL密码
2017/05/03 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
解决pycharm上的jupyter notebook端口被占用问题
2019/12/17 Python
python ftplib模块使用代码实例
2019/12/31 Python
运动鞋、街头服装、手表和手袋的实时市场:StockX
2020/11/25 全球购物
C#笔试题和英文面试题
2013/02/07 面试题
可以使用抽象函数重写基类中的虚函数吗
2013/06/02 面试题
艺术应用与设计专业个人的自我评价
2013/11/19 职场文书
亲戚结婚的请假条
2014/02/11 职场文书
四风存在的原因分析
2014/02/11 职场文书
无刑事犯罪记录证明范本
2014/09/29 职场文书
主持人开幕词
2015/01/29 职场文书
以权谋私检举信范文
2015/03/02 职场文书
工作自我评价范文
2015/03/05 职场文书