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 相关文章推荐
window.addEventListener来解决让一个js事件执行多个函数
Dec 26 Javascript
jquery图形密码实现方法
Mar 11 Javascript
jQuery给多个不同元素添加class样式的方法
Mar 26 Javascript
javascript弹出拖动窗口
Aug 11 Javascript
AngularJS  双向数据绑定详解简单实例
Oct 20 Javascript
详解照片瀑布流效果(js,jquery分别实现与知识点总结)
Jan 01 Javascript
基于Bootstrap漂亮简洁的CSS3价格表(附源码下载)
Feb 28 Javascript
JS返回页面时自动回滚到历史浏览位置
Sep 26 Javascript
element上传组件循环引用及简单时间倒计时的实现
Oct 01 Javascript
JavaScript实现单图片上传并预览功能
Sep 30 Javascript
基于JS+HTML实现弹窗提示是否确认提交功能
Jun 17 Javascript
使用typescript快速开发一个cli的实现示例
Dec 09 Javascript
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
生成缩略图
2006/10/09 PHP
用PHP制作静态网站的模板框架(一)
2006/10/09 PHP
jQuery+php实现ajax文件即时上传的详解
2013/06/17 PHP
PHP开发微信支付的代码分享
2014/05/25 PHP
PHP使用json_encode函数时不转义中文的解决方法
2014/11/12 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
2015/10/19 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
javascript 小数取整简单实现方式
2014/05/30 Javascript
DOM基础教程之使用DOM控制表单
2015/01/20 Javascript
编写自己的jQuery提示框(Tip)插件
2015/02/05 Javascript
原创jQuery弹出层插件分享
2015/04/02 Javascript
nodejs通过phantomjs实现下载网页
2015/05/04 NodeJs
jQuery实现返回顶部效果的方法
2015/05/29 Javascript
jQuery实现带滑动条的菜单效果代码
2015/08/26 Javascript
js实现改进的仿蓝色论坛导航菜单效果代码
2015/09/06 Javascript
jquery动态切换背景图片的简单实现方法
2016/05/14 Javascript
快速解决js动态改变dom元素属性后页面及时渲染的问题
2016/07/06 Javascript
js style.display=block显示布局错乱问题的解决方法
2016/09/21 Javascript
js判断是否为空和typeof的用法(详解)
2016/10/07 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
2017/04/11 Javascript
关于微信小程序登录的那些事
2019/01/08 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
解决vue打包 npm run build-test突然不动了的问题
2020/11/13 Javascript
java直接调用python脚本的例子
2014/02/16 Python
Python日志模块logging基本用法分析
2018/08/23 Python
基于Python3.7.1无法导入Numpy的解决方式
2020/03/09 Python
CSS3之transition实现下划线的示例代码
2018/05/30 HTML / CSS
Sixt美国租车:高端豪华车型自驾体验
2017/09/02 全球购物
美国体育用品商店:Academy Sports + Outdoors
2020/01/04 全球购物
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
简短证婚人证婚词
2014/01/09 职场文书
淘宝客服专员岗位职责
2014/04/11 职场文书
2014年社团工作总结范文
2014/11/27 职场文书
违反工作规定检讨书范文
2014/12/14 职场文书
初二物理教学反思
2016/02/19 职场文书
Oracle 多表查询基本语法实例
2022/04/18 Oracle