JS类的封装及实现代码


Posted in Javascript onDecember 02, 2009

1. 定义js类
js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类.

function ShapeBase() { 
this.show = function() 
{ 
alert("ShapeBase show"); 
}; 
this.init = function(){ 
alert("ShapeBase init"); 
}; 
}

这个类里定义了两个方法:show和init, 需要注意的是这里用到了this来声明, 而不是var, 因为用var是用来定义私有方法的.
另外, 我们还可以用prototype属性来定义Shape的方法.
ShapeBase.prototype.show=function() 
{ 
alert("ShapeBase show"); 
} 
ShapeBase.prototype.init=function() 
{ 
alert("ShapeBase init"); 
}

上面这种写法看起来不太直观,我们可以将所有的方法写在一起.
ShapeBase.prototype={ 
show:function() 
{ 
alert("ShapeBase show"); 
}, 
init:function() { 
alert("ShapeBase init"); 
} 
};

现在, 类是写好了, 让我们写个js来测试下, 看看结果是不是跟我们想象的一样呢?
function test(src){ 
var s=new ShapeBase(); 
s.init(); 
s.show(); 
}

看到了吧, 其调用方式和C#一模一样, 而结果也如我们所料.
到目前为止, 我们学会了如何创建js的类了, 但还只是实例方法,要是实现跟C#中的静态方法要怎么做呢?
其实, 实现js的静态方法很简单, 看下面如何实现:
//静态方法 
ShapeBase.StaticDraw = function() 
{ 
alert("method draw is static"); 
}

2. 实现JS类抽象和继承
同样, js中也不支持类继承机制,但我们可以通过将父类prototype中的成员方法复制到子类的prototype中来实现.
和类的继承一样,JavaScript也没有任何机制用于支持抽象类.但利用JavaScript语言本身的性质.可以实现自己的抽象类.
首先来看看js中的虚方法, 在传统语言中虚方法是要先定义的, 而包含虚方法的类就是抽象类,不能被实例化,而在JavaScript中,虚方法就可以看作该类中没有定义的方法,但已经通过this指针使用了.
和传统面向对象不同的是,这里虚方法不需经过声明,而直接使用了, 并且类也可以被实例化.
先定义object的extend方法, 一个为静态方法,一个为实例方法, 这两个方法用于实现继承的prototype复制
Object.extend = function(destination, source) { 
for (property in source) { 
destination[property] = source[property]; 
} 
return destination; 
} 
Object.prototype.extend = function(object) { 
return Object.extend.apply(this, [this, object]); 
}

接下来我们实现一个继承类Rect, 这里先用一种简单的方法来实现。
function Rect() { 
} 
Rect.prototype = ShapeBase.prototype; //只这一句就行了 
//扩充新的方法 
Rect.prototype.add=function() { 
alert("Rect add"); 
}

这种方法不能用于重写,如果改变了show方法, ShapeBase的show也会指向同一函数可能是由于prototype赋值只是简单的改变指向地址.
如果上面也定义了:
Rect.prototype.show=function() {
alert("Rect show");
}
那么执行结果如下:
function test(){
var s=new ShapeBase();
s.show(); //结果:Rect show
var r=new Rect();
r.show(); //结果:Rect show
r.add();
}
我们再使用object.extend实现继承, 并实现一个oninit虚方法, 修改ShapeBase如下:
ShapeBase.prototype={ 
show:function() 
{ 
alert("ShapeBase show"); 
}, 
initialize:function () { 
this.oninit(); 
} 
};

实现Rect类继承.
Rect.prototype=(new ShapeBase).extend({ 
//添加新的方法 
add:function() { 
alert("Rect add"); 
}, 
//使用这种方法可以重写show方法 
show:function() { 
alert("Rect show"); 
}, 
//实现虚方法 
oninit:function() { 
alert("Rect oninit"); 
} 
})

现在我们的类写好了, 测试下看看:
function test(src){ 
ShapeBase.StaticDraw(); 
var s=new ShapeBase(); 
s.show(); //alert("ShapeBase show") 
var r=new Rect(); 
r.show(); //alert("Rect show") 
r.add(); 
r.initialize(); //alert("Rect oninit") 
}

另外,在网上看到一篇用专门的对象来创建类,代码如下:
// 
//对象属性复制方法,很多库都有实现,如PrototypeJS里面的extend和Ext里面的Ext.apply 
// 
function extend(des, src) { 
if (!des) 
des = {}; 
if (src) { 
for (var i in src) { 
des[i] = src[i]; 
} 
} 
return des; 
} 
var CC = {}; //全局变量 
// 
//create 用于创建类 
// 
CC.create = function(superclass, constructor){ 
var clazz = (function() { 
this.initialize.apply(this, arguments); 
}); 
//如果无参数,直接返回类. 
if(arguments.length == 0) 
return clazz; 
//如果无父类,此时constructor应该为一个纯对象,直接复制属性返回. 
if(!superclass){ 
extend(clazz.prototype, constructor); 
return clazz; 
} 
var absObj = clazz.prototype, 
sprPropty = superclass.prototype; 
if(sprPropty){ 
//用于访问父类方法 
clazz.superclass = sprPropty; 
extend(absObj, sprPropty); 
//调用属性构造函数创建属性,这个是实现关键. 
extend(absObj, constructor(sprPropty)); 
// 子类实例直接通过obj.superclass访问父类属性, 
// 如果不想造成过多引用,也可把这句注释掉,因为多数时候是没必要的. 
absObj.superclass = sprPropty; 
// 
clazz.constructor = constructor; 
} 
return clazz; 
} 
// 
//创建一个动物类 
// 
var Animal = CC.create(null, { 
//属性 
footprint : '- - - - - - =', 
//类初始化方法,必须的,当用 new 生成一个类时该方法自动被调用,参见上定义. 
initialize : function(options){ 
extend(this, options); 
alert('Animal initialize method is called.'); 
}, 
eat : function(){ 
alert('Animal eat method is called.'); 
}, 
move : function(){ 
alert('I am moving like this '+ this.footprint +' .'); 
} 
}); 
// 
//创建一个Duke类 
// 
var Duke = CC.create(Animal, function(superclass){ 
//在这可以定义一些类全局静态数据,该类每个实例都共享这些数据. 
//计算实例个类,包括派生类实例. 
var static_instance_counter = 0; 
function classUtilityFuncHere(){ } 
//返回类具体属性. 
return { 
//重写初始化方法 
//@override 
initialize : function(options) { 
alert('Initializing Duke class..'); 
//调用父类初始化,这种方法比一般其它库的要简洁点吧,可以不管父类是什么. 
superclass.initialize.call(this, options); 
//做一些子类喜欢做的事. 
alert('Duke initialize method is called.'); 
//读取或修改类静态属性 
static_instance_counter++; 
}, 
//重写move方法,增加Duke自己的移动方式. 
move : function(){ 
this.footprint = this.footprint + 'zzzzzzzz'; 
superclass.move.call(this); 
}, 
//重写eat方法,注意,里面不调用父类方法,即父类eat被覆盖了. 
eat : function(){ 
alert('Duke is eating..'); 
}, 
//新增一个say方法,显示当前已经初始化的Duke类实例数量. 
say : function(){ 
alert('the number of Duke instances is '+static_instance_counter); 
} 
}; 
}); 
var DukeChild = CC.create(Duke, function(superclass){ 
return { 
move : function(){ 
this.footprint = this.footprint + '++++++++++++='; 
superclass.move.call(this); 
}, 
say : function(){ 
alert(this.msg || ''); 
} 
}; 
}); 
(function test() { 
var animal = new Animal(); 
animal.eat(); 
animal.move(); 
var dukeA = new Duke(); 
dukeA.eat(); 
dukeA.move(); 
dukeA.say(); 
var dukeB = new Duke(); 
dukeB.eat(); 
dukeB.move(); 
dukeB.say(); 
var dukeC = new DukeChild({msg : 'I am a child of duke.'}); 
dukeC.move(); 
dukeC.say(); 
})();
Javascript 相关文章推荐
Extjs学习笔记之七 布局
Jan 08 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
Feb 24 Javascript
JS防止用户多次提交的简单代码
Aug 01 Javascript
JsRender for index循环索引用法详解
Oct 31 Javascript
去除字符串左右两边的空格(实现代码)
May 12 Javascript
javascript判断回文数详解及实现代码
Feb 03 Javascript
利用Jasmine对Angular进行单元测试的方法详解
Jun 12 Javascript
node版本管理工具n包使用教程详解
Nov 09 Javascript
Vue filter 过滤当前时间 实现实时更新效果
Dec 20 Javascript
详解Vue之计算属性
Jun 20 Javascript
JavaScript JSON使用原理及注意事项
Jul 30 Javascript
Vue+Bootstrap实现简易学生管理系统
Feb 09 Vue.js
Jquery选择器 $实现原理
Dec 02 #Javascript
js 表格隔行颜色
Dec 02 #Javascript
让FireFox支持innerText的实现代码
Dec 01 #Javascript
JavaScript 直接操作本地文件的实现代码
Dec 01 #Javascript
js 变量类型转换常用函数与代码[比较全]
Dec 01 #Javascript
Jquery 快速构建可拖曳的购物车DragDrop
Nov 30 #Javascript
JavaScript 学习笔记 Black.Caffeine 09.11.28
Nov 30 #Javascript
You might like
php定义一个参数带有默认值的函数实例分析
2015/03/16 PHP
Smarty保留变量用法分析
2016/05/23 PHP
用javascript实现在小方框中浏览大图的代码
2007/08/14 Javascript
JQuery 学习笔记 选择器之六
2009/07/23 Javascript
js 时间函数应用加、减、比较、格式转换的示例代码
2013/08/23 Javascript
js获取当月最后一天实例代码
2013/11/19 Javascript
node.js超时timeout详解
2014/11/26 Javascript
Node.js实现Excel转JSON
2015/04/24 Javascript
jQuery实现textarea自动增长宽高的方法
2015/12/18 Javascript
微信小程序使用第三方库Underscore.js步骤详解
2016/09/27 Javascript
JavaScript数据结构中栈的应用之表达式求值问题详解
2017/04/11 Javascript
JavaScript中EventLoop介绍
2018/01/22 Javascript
Vue项目部署在Spring Boot出现页面空白问题的解决方案
2018/11/26 Javascript
ES6中异步对象Promise用法详解
2019/07/31 Javascript
[57:16]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第二场
2014/05/26 DOTA
Python使用os模块和fileinput模块来操作文件目录
2016/01/19 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
2019/01/22 Python
Python占用的内存优化教程
2019/07/28 Python
Python使用matplotlib 模块scatter方法画散点图示例
2019/09/27 Python
在Python中利用pickle保存变量的实例
2019/12/30 Python
python实现将字符串中的数字提取出来然后求和
2020/04/02 Python
Python如何脚本过滤文件中的注释
2020/05/27 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
HTML5 CSS3给网站设计带来出色效果
2009/07/16 HTML / CSS
Java软件工程师综合面试题笔试题
2013/09/08 面试题
幼儿园亲子活动方案
2014/01/29 职场文书
幼儿园教学随笔感言
2014/02/23 职场文书
聚美优品的广告词
2014/03/14 职场文书
领导党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
六一儿童节开幕词
2015/01/29 职场文书
毕业生党员个人总结
2015/02/14 职场文书
社区国庆节活动总结
2015/03/23 职场文书
2015学生会文艺部工作总结
2015/04/03 职场文书
电影雷锋观后感
2015/06/10 职场文书
MySQL中distinct与group by之间的性能进行比较
2021/05/26 MySQL
Python+OpenCV实现图片中的圆形检测
2022/04/07 Python