《悟透JavaScript》之 甘露模型(4)
作者:李战 来源:软件真谛 发布时间:2008-06-09 14:03:00
这可真是闭包中嵌套着闭包,貌似递归却又不是递归,是高阶函数却又高不可测。一旦整个对象创建完成,用过的内存状态都释放得干干净净,只得到一尘不染的新建对象。JavaScript玩到这样的境界,方显观音大士的法力!
下面就是是重写后的完美甘露模型代码:
http://www.leadzen.cn/Books/WuTouJavaScript/1/JS25.htm
<script type="text/javascript">
//定义类的语法甘露:Class()
//最后一个参数是JSON表示的类定义
//如果参数数量大于1个,则第一个参数是基类
//第一个和最后一个之间参数,将来可表示类实现的接口
//返回值是类,类是一个构造函数
function Class()
{
var aDefine = arguments[arguments.length-1]; //最后一个参数是类定义
if(!aDefine) return;
var aBase = arguments.length>1 ? arguments[0] : object; //解析基类
function prototype_(){}; //构造prototype的临时函数,用于挂接原型链
prototype_.prototype = aBase.prototype; //准备传递prototype
var aPrototype = new prototype_(); //建立类要用的prototype
for(var member in aDefine) //复制类定义到当前类的prototype
if(member!="Create") //构造函数不用复制
aPrototype[member] = aDefine[member];
//根据是否继承特殊属性和性能情况,可分别注释掉下列的语句
if(aDefine.toString != Object.prototype.toString)
aPrototype.toString = aDefine.toString;
if(aDefine.toLocaleString != Object.prototype.toLocaleString)
aPrototype.toLocaleString = aDefine.toLocaleString;
if(aDefine.valueOf != Object.prototype.valueOf)
aPrototype.valueOf = aDefine.valueOf;
if(aDefine.Create) //若有构造函数
var aType = aDefine.Create //类型即为该构造函数
else //否则为默认构造函数
aType = function()
{
this.base.apply(this, arguments); //调用基类构造函数
};
aType.prototype = aPrototype; //设置类(构造函数)的prototype
aType.Base = aBase; //设置类型关系,便于追溯继承关系
aType.prototype.Type = aType; //为本类对象扩展一个Type属性
return aType; //返回构造函数作为类
};
//根类object定义:
function object(){} //定义小写的object根类,用于实现最基础的方法等
object.prototype.isA = function(aType) //判断对象是否属于某类型
{
var self = this.Type;
while(self)
{
if(self == aType) return true;
self = self.Base;
};
return false;
};
object.prototype.base = function() //调用基类构造函数
{
var Base = this.Type.Base; //获取当前对象的基类
if(!Base.Base) //若基类已没有基类
Base.apply(this, arguments) //则直接调用基类构造函数
else //若基类还有基类
{
this.base = MakeBase(Base); //先覆写this.base
Base.apply(this, arguments); //再调用基类构造函数
delete this.base; //删除覆写的base属性
};
function MakeBase(Type) //包装基类构造函数
{
var Base = Type.Base;
if(!Base.Base) return Base; //基类已无基类,就无需包装
return function() //包装为引用临时变量Base的闭包函数
{
this.base = MakeBase(Base); //先覆写this.base
Base.apply(this, arguments); //再调用基类构造函数
};
};
};
//语法甘露的应用效果:
var Person = Class //默认派生自object基本类
({
Create: function(name, age)
{
this.base(); //调用上层构造函数
this.name = name;
this.age = age;
},
SayHello: function()
{
alert("Hello, I'm " + this.name + ", " + this.age + " years old.");
},
toString: function() //覆写toString方法
{
return this.name;
}
});
var Employee = Class(Person, //派生自Person类
{
Create: function(name, age, salary)
{
this.base(name, age); //调用基类的构造函数
this.salary = salary;
},
ShowMeTheMoney: function()
{
alert(this + " $" + this.salary); //这里直接引用this将隐式调用toString()
}
});
var BillGates = new Person("Bill Gates", 53);
var SteveJobs = new Employee("Steve Jobs", 53, 1234);
alert(BillGates); //这里将隐式调用覆写后的toString()方法
BillGates.SayHello();
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
var LittleBill = new BillGates.Type("Little Bill", 6); //用BillGate的类型建LittleBill
LittleBill.SayHello();
alert(BillGates.isA(Person)); //true
alert(BillGates.isA(Employee)); //false
alert(SteveJobs.isA(Person)); //true
</script>
当今的JavaScript世界里,各式各样的AJAX类库不断出现。同时,在开放Web API的大潮中,AJAX类库作为Web API最重要的形式,起着举足轻重的作用。这些AJAX类库是否方便引用,是否易于扩展,是否书写优雅,都成了衡量Web API质量的重要指标。
甘露模型基于JavaScript原型机制,用及其简单的Class()函数,构造了一个非常优雅的面向对象的类机制。事实上,我们完全可以在这个甘露模型的基础上打造相关的的AJAX类库,为开发人员提供简洁而优雅的Web API接口。
想必微软那些设计AJAX架构的工程师看到这个甘露模型时,肯定后悔没有早点把AJAX部门从美国搬到咱中国的观音庙来,错过了观音菩萨的点化。
当然,我们也只能是在代码的示例中,把Bill Gates当作对象玩玩,真要让他放弃上帝转而皈依我佛肯定是不容易的,机缘未到啊!如果哪天你在微软新出的AJAX类库中看到这种甘露模型,那才是真正的缘分!
广告时间:《悟透JavaScript》一书,共分三部分,
第一部分 JavaScript真经 (博客原文扩编)
第二部分 手谈JavaScript (讲述JavaScript操纵DOM)
第三部分 点化AJAX (AJAX思维升华)
就算你不看,也可以给孩子当故事书。如果你还没孩子,就当给自己买本幽默的漫画书。
原创 * :李战(leadzen)
幕后指使:电子工业出版社-博文视点公司


猜你喜欢
- 1、简介本文主要给大家介绍了关于Laravel 5用Laravel Excel实现Excel/CSV文件导入导出的相关内容,下面话不多说了,
- ExecuteReader(),ExecuteNonQuery(),ExecuteScalar(),ExecuteXmlReader()之间
- 开发的时候我都是使用XDebug在本地调试,但是最近加入一些项目中去,环境太复杂了,要在本地搭建一个开发环境真的太麻烦了,那么我们怎么使用x
- 0 引言前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇
- pyqtgraph是Python平台上一种功能强大的2D/3D绘图库,相对于matplotlib库,由于其在内部实现方式上,使用了高速计算的
- 前言所谓模糊查询就是不需要用户完整的输入或者说全部输入信息即可提供查询服务,也就是用户可以在边输入的同时边看到提示的信息(其实是查询出来匹配
- 随着编程语言的发展,Go 还很年轻。它于 2009 年 11 月 10 日首次发布。其创建者Robert GriesemerRob Pike
- tf定义了tf.app.flags,用于支持接受命令行传递参数,相当于接受argv。import tensorflow as tf#第一个是
- 一、异常处理在程序开发中如果遇到一些 不可预知的错误 或 你懒得做一些判断 时,可以选择用异常处理来做。import requestswhi
- 引言webpack插件CommonsChunkPlugin的主要作用是抽取webpack项目入口chunk的公共部分,具体的用法就不做过多介
- 生成静态页的方法有很多种,我比较喜欢用xmlhttp的方法生成,因为我不用考虑很多东西,我只要把动态的asp页面编写好就行了。<% s
- 支持CSS属性Safari和WebKit实施大子的CSS 2.1规格所界定的万维网联盟( W3C ) ,以及部分的CSS 3规格。 。这个C
- 过渡效果在交互体验中的重要性不言而喻。以往我们使用js或Jquery添加或移除元素的类(class),搭配CSS中定义好的样式,再引用一些j
- 其实图像识别技术与我们平时做的密码验证之类的没有什么区别,都是事先把要校验的数据入库,然后使用时将录入(识别)的数据与库中的数据做对比,只不
- 本文实例讲述了javascript实现获取图片大小及图片等比缩放的方法。分享给大家供大家参考,具体如下:获取图片大小:var originI
- pandas中有时需要按行依次对.csv文件读取内容,那么如何进行呢?我们来完整操作一遍,假设我们已经有了一个.csv文件。# 1.导入包i
- 一、安装pip install xlwt二、创建表格并写入import xlwt# 创建一个workbook并设置编码workbook =
- 前言:要说小时候称霸所有翻盖手机的小游戏,除了贪吃蛇,那就是推箱子了。控制小人将所有箱子放到指定位置,就是这样简简单单的操作,陪伴我度过了无
- zip()的作用先看一下语法:zip(iter1 [,iter2 [...]]) —> zip objectPython的内置help
- 先看一下flask-login模块的整体架构基础的信息和全局配置这里就不多说,需要用到再斟酌也可以的。这里也是针对每个模块较为常用的进行解释