工具包 Base
Base 是由 Dean Edwards 开发的一个 JavaScript 的面向对象的基础包,Base 本身很小,只有 140 行,但是这个很小的包对面向对象编程风格有很好的支持,支持类的定义, 封装,继承,子类调用父类的方法等,代码的质量也很高,而且很多项目都在使用 Base 作 为底层的支持。尽管如此,JavaScript 的面向对象风格依然非常古怪,并不可以完全和传统的 OO 语言对等起来。
下面我们来看几个基于 Base 的例子,假设我们现在在开发一个任务系统,我们需要抽象出一个类来表示任务,对应的,每个任务都可能会有一个监听器,当任务执行之后,需要通知监听器。我们首先定义一个事件监听器的类,然后定义一个任务类:
var EventListener = Base.extend({
constructor : function(sense){
this.sense = sense;
},
sense : null,
handle : function(){
print(this.sense+" occured");
}
});
var Task = Base.extend({
constructor : function(name){
this.name = name;
},
name : null,
listener : null,
execute : function(){
print(this.name);
this.listener.handle();
},
setListener : function(listener){
this.listener = listener;
}
});
创建类的方式很简单,需要给 Base.extend 方法传入一个 JSON 对象,其中可以有成员和方法。方法访问自身的成员时需要加 this 关键字。而每一个类都会有一个 constructor 的 方法,即构造方法。比如事件监听器类(EventListener)的构造器需要传入一个字符串,而任务类(Task)也需要传入任务的名字来进行构造。好了,既然我们已经有了任务类和事件监听器类,我们来实例化它们:
var printing = new Task("printing");
var printEventListener = new EventListener("printing");
printing.setListener(printEventListener);
printing.execute();
首先,创建一个新的 Task,做打印工作,然后新建一个事件监听器,并将它注册在新建的 任务上,这样,当打印发生时,会通知监听器,监听器会做出相应的判断:
printing
printing occurred
既然有了基本的框架,我们就来使用这个框架,假设我们要从 HTTP 服务器上下载一个页面,于是我们设计了一个新的任务类型,叫做 HttpRequester
:
var HttpRequester = Task.extend({
constructor : function(name, host, port){
this.base(name);
this.host = host;
this.port = port;
},
host : "127.0.0.1",
port : 9527,
execute : function(){
print("["+this.name+"] request send to "+this.host+" of port "+this.port);
this.listener.handle();
}
});
HttpRequester 类继承了 Task,并且重载了 Task 类的 execute 方法,setListener 方法的内容与父类一致,因此不需要重载。
var requester = new HttpRequester("requester1", "127.0.0.1", 8752);
var listener = new EventListener("http_request");
requester.setListener(listener);
requester.execute();
我们新建一个 HttpRequester
任务,然后注册上事件监听器,并执行之:
[requester1] request send to 127.0.0.1 of port 8752
http_request occured
应该注意到 HttpRequester
类的构造器中,有这样一个语句:
this.base(name);
表示执行父类的构造器,即将 name 赋值给父类的成员变量 name,这样在 HttpRequester 的实例中,我们就可以通过 this.name 来访问这个成员了。这套机制简直与在其他传统的 OO 语言并无二致。同时,HttpRequester 类的 execute 方法覆盖了父类的 execute 方法,用面向对象的术语来讲,叫做重写。
在很多应用中,有些对象不会每次都创建新的实例,而是使用一个固有的实例,比如提供数据源的服务,报表渲染引擎,事件分发器等,每次都实例化一个会有很大的开销,因此 人们设计出了单例模式,整个应用的生命周期中,始终只有顶多一个实例存在。Base 同样可以模拟出这样的能力:
var
ReportEngine = Base.extend({
constructor : null,
run : function(){
//render the report
}
});
很简单,只需要将构造函数的值赋为 null 即可。好了,关于 Base 的基本用法我们已经熟悉了,来看看用 Base 还能做点什么:
{$ activeFileHint $}