JS类的封装及实现代码
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来测试下, 看看结果是不是跟我们想象的一样呢?
看到了吧, 其调用方式和C#一模一样, 而结果也如我们所料. 到目前为止, 我们学会了如何创建js的类了, 但还只是实例方法,要是实现跟C#中的静态方法要怎么做呢? 其实, 实现js的静态方法很简单, 看下面如何实现:
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类继承.
//添加新的方法 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") }
另外,在网上看到一篇用专门的对象来创建类,代码如下:
- 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();
- })();
JS类的封装及实现代码的更多相关文章
- 自己手写的自动完成js类
在web开发中,为了提高用户体验,会经常用到输入框的自动完成功能,不仅帮助用户进行快速输入,最重要的是帮助那些“记不全要输入什么”的用户进行选择.这个功能有很多插件已经实现了,为了适应项目的特殊需求, ...
- js类(继承)(二)
1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Sh ...
- 【转】第7篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:全自动注册与反射方法分析
作者: 牛A与牛C之间 时间: 2013-12-12 分类: 技术文章 | 2条评论 | 编辑文章 主页 » 技术文章 » 第7篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- 【转】第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析
作者: 牛A与牛C之间 时间: 2013-11-21 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第6篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- 【转】第5篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+委托回调方法分析
作者: 牛A与牛C之间 时间: 2013-11-19 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第5篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- 【转】第4篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:委托回调方法分析
作者: 牛A与牛C之间 时间: 2013-11-18 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第4篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- 【转】3篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:官方原生方法分析
作者: 牛A与牛C之间 时间: 2013-11-17 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第3篇:Xilium CefGlue 关于 CLR Object 与 JS ...
- JS类继承常用方式发展史
JS类继承常用方式发展史 涉及知识点 构造函数方式继承 1-继承单个对象 1.1 多步走初始版 1.2 多步走优化版 1.3 Object.create()方式 2-继承多个对象 2.1 遍历 Obj ...
- JS对象之封装(二)
JS 对象封装的常用方式 1.常规封装 function Person (name,age){ this.name = name; this.age = age; } Pserson.prototyp ...
随机推荐
- MVC基础知识 – 2.新语法
1.自动属性 Auto-Implemented Properties 2.隐式类型 var 3.参数默认值 和 命名参数 4.对象初始化器 与 集合初始化器 { } 5.匿名类 & 匿名方法 ...
- 微信token验证失败的解决方法
一.问题由来 在使用URL和Token启用微信公众平台开发模式消息接口的时候,我们会碰到下面三种情况 1. token校验失败 这样回头检查一下各项配置是否正确.如果确定配置没有问题,请按下面的方法检 ...
- 使用Autofac在ASP.NET Web API上实现依赖注入
在ASP.NET Web API里使用Autofac 1.通过NuGet安装Autofac.WebApi(当时安装的是Autofac 3.1.0) PM > Install-Package Au ...
- Powershell查看SSAS Cube占用磁盘空间
以下是用powershell查看Cube占用磁盘空间大小的方式.可以编译成函数也可以直接把参数改成需要的服务器名称. Param($ServerName="SERVERNAME") ...
- golang time and duration
package mainimport "fmt"import "time"func main() { p := fmt.Println // We'll sta ...
- 计算G711语音的打包长度和RTP里timestamp(时间戳)的增长量
转自:http://blog.csdn.net/xujianglun/article/details/48342367 如何计算G711语音等的打包长度和RTP里timestamp的增长量 一般对于不 ...
- hpunix下11gRac的安装
一.检查环境 1.操作系统版本# uname -a 2.补丁包三大补丁包#swlist -l bundle|grep QPKAPPS#swlist -l bundle|grep QPKBASE#swl ...
- 第三篇:用SOUI能做什么?
SOUI-DEMO界面预览 在回答SOUI能做什么之前,先看看SVN中demo工程的界面截图: 使用SOUI实现上面的界面主要的工作全在配置几个XML文件,基本不需要写C++代码.(如何配置XML布局 ...
- android在代码中四种设置控件(以及TextView的文字颜色)背景颜色的方法
http://blog.csdn.net/fth826595345/article/details/9208771 主题 TextView 转载请注明出处: http://blog.csdn.ne ...
- ios录音
#import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewCont ...