《悟透JavaScript》之 甘露模型(3)
作者:李战 来源:软件真谛 发布时间:2008-06-09 14:03:00
其实,base()方法之所以要使用自身的caller属性,就是为了确定当前构造函数的层次,从而可以知道该调用更上层的构造函数。有没有别的办法来知道是那层构造函数调用了base()方法呢?残酷的事实告诉我们,除了函数自身的caller属性,没有办法知道是谁调用了自己。
既然改变不了别人,那就改变自己!我们为什么就不能在运行中改变base()自身呢?
事实上,第一层构造函数调用this.base()时,我们是可以过this.Type属性知道地一层构造函数的,而this.Type.Base就是第二层构造函数。只是,第二层构造函数又会调用this.base(),其本来是想调用第三层的构造函数,但再次进入base()函数时,就无法知晓构造函数的层次了。
如果我们在第一层构造函数调用进入this.base()时,先改变this.base本身,让其在下次被调用时能掉到第三层构造函数。完成这个变身动作之后再调第二层构造函数,而第二层构造函数再调用this.base()时就能调用到第三层构造函数了。这样,只要我们在每次的base()调用中都完成一个自我的变身动作,就可以按正确的顺序完成对构造函数的调用。这是多么有趣的调用方式啊!
于是,我们可以将原来的base()函数改写成下面的形式:
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); //再调用基类构造函数
};
};
};
原来的base()函数只有两行代码,而新的base()函数却又十几行代码。看来为了支持Opera浏览器确实也付出了代价,好在这些代码只有十来行,代价并不是太大。当然,如果无须支持Opera浏览器,也就不必用这个base()函数了。
在这个新的base()函数中,对this.base的覆写实际上只是在this对象身上创建了一个临时的base方法。这个临时方法暂时遮住了object.prototype.base方法,而object.prototype.base方法却一直存在。而每次对this.base的变身操作,都是针对这个临时的方法的。当所有层次构造函数的调用都完成之后,即可删除this对象的这个临时base方法。
其中的MakeBase()函数非常有意思,如果基类还有基类,它就返回一个闭包函数。下次this.base()被构造函数调用时,即调用的是这个闭包函数。但这个闭包函数又可能会调用MakeBase()形成另一个闭包函数,直到基类再无基类。
如果说这是递归调用呢?却并非那种函数自身对自身的直接或间接调用,而是调用一个函数却返回另一个函数,再调用返回的函数又会在其中产生新的返回函数。如果说是函数式编程中的高阶函数调用呢?这函数的嵌套阶数却是与类层次相关的不确定数,而每一个阶梯都有新生成的函数。
猜你喜欢
- 金额大小写转换的asp完全无错版本, 这个版本解决了小数位不能到分的问题,处理方式符合会计方式,值得推荐!<!--#inc
- 在我们制作主页的过程中,用到表格的地方非常多,灵活运用表格技巧可以为我们的网页增色不少,这里我就详细介
- caller 属性返回一个对函数的引用,该函数调用了当前函数。functionName.caller functionName 对象是所执行
- 如何在网页打开时显示“正在加载”之类的信息?代码及说明见下: <% Response.Buffer =
- 一个网站的导航就相当于是一条路的路标,不同的是,网站的不同栏目页的入口远远比马路要来得复杂,所以一个清晰的导航设计对于一个网站的意义远远大于
- sql server端口,我们可以通过\"服务器端网络试用工具\"和\"客户端实用工具\"来设定,设
- 在做网站产品展示页面时,一般会用到缩略图,好处当然是直观醒目让人一目了然。点击进入然后看到大图及具体的介绍。但是缩略图在实现上带来了两个问题
- 密码已经是我们生活工作中必不可少的工具,但一个不安全的密码有又有可能会给我们造成不必要的损失。作为网站设计者,如果我们在网页中能对用户输入的
- 当你提交一个查询的时候,MySQL会分析它,看是否可以做一些优化使处理该查询的速度更快。这一部分将介绍查询优化器是如何工作的。如果你想知道M
- 昨天在W3C看到,6月10日发布了新的 HTML 5 草案(Working Draft)。粗略的读了一下它提供的 新版本说明文档 ,作了一点
- 我认为多选列表具有完美的功能——只需按下Ctrl键,同时点击鼠标从列表中选择多个项目。以下是一个典型的多选列表框: 上面那个列表框
- 在开发过程中,有时遇到由于缓存问题导致页面不能及时更新,有时页面引入了不必需的样式脚本文件,有时由于文件太多,字节过大导致页面的性能缓慢,为
- 我们可使用Haskeys属性判别每个条目是否为一个集合,遍历完整的Request.Cookies集合,以来取得所有cookie的列表及其值:
- 此文章主要向大家描述的是MySQL高级查询方法之记录查询的实际操作步骤,以及对其实际操作过程中要用到的代码的详细描述,以下就是文章的主要内容
- XML同HTML一样,都来自Standard Generalized Markup Language, 即标准通用标记语言,简称SGML。早
- 通配符:通配符描述示例%包含零个或更多字符的任意字符串。WHERE title LIKE '%computer%' 将查找处
- 一条语句搞定数据库分页select top 10 b.* from (select&nbs
- 很简单,只需建立一个worksheet和Excel相关的信息就可以了具体代码见下:<%set xlApp =&nb
- 在网页设计发展到一定阶段的时候就必然会和其他学科或领域只是产生交汇和共鸣,在阅读《超越CSS:web设计艺术精髓》这本书的时候,发现原来we
- asp如何显示全部的环境变量?<%@Language="VBScript"%><%dim H