《悟透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()形成另一个闭包函数,直到基类再无基类。
如果说这是递归调用呢?却并非那种函数自身对自身的直接或间接调用,而是调用一个函数却返回另一个函数,再调用返回的函数又会在其中产生新的返回函数。如果说是函数式编程中的高阶函数调用呢?这函数的嵌套阶数却是与类层次相关的不确定数,而每一个阶梯都有新生成的函数。


猜你喜欢
- ORA-01578:Oracle data block corrupted(file # num,block # num)产生原
- 1、函数介绍REGEXP_LIKE 函数在功能上与 LIKE 函数非常相似。 然而,虽然 LIKE 允许简单的字符串匹配搜索,但 REGEX
- 🥩数据采集🍖确定网址王者新赛季马上就要开始了,大家都开始冲榜了,准备拿一个小省标,那么,本文,就来练习获取各地最低战力的爬虫采集实战。确定好
- 下载python3.6.5安装包1. 上传安装包。打开终端,利用命令cd 进入文件所在文件夹里python@ubun
- Mac下mysql安装配置方法图文教程记录如下使用安装包安装mysql双击pkg文件安装一路向下,记得保存最后弹出框中的密码(它是你mysq
- 其实大家都知道sql语句的错误信息都可以在sys.messages表里面找到如:如果在执行语句在try...catch中 我们可以通过以下方
- 整体思路将要备份的目录列为一个列表,通过执行系统命令,进行压缩、备份。这样关键在于构造命令并使用 os.system( )来执行,一开始使用
- 0 前言安装:pip install pypiwin32 1 Excel的APIimport win32com.client as win3
- 本文记录了笔者用 Python 爬取淘宝某商品的全过程,并对商品数据进行了挖掘与分析,最终得出结论。项目内容本案例选择>> 商品
- 我就废话不多说了,直接上代码吧!# -*- coding: utf-8 -*-"""Created on Sa
- print(X.shape):查看矩阵的行列号print(len(X)):查看矩阵的行数print(X.ndim):查看矩阵的维数1 查看矩
- 我们经常会在登录一个网站的时候被引导页挡住前进的脚步,这一点在上个世纪到本世纪初的网站中尤其明显,特别是在企业网站里,几乎每个企业网站都会有
- 本文实现了PyQt5个各种弹出窗口:输入框、消息框、文件对话框、颜色对话框、字体对话框、自定义对话框其中,为了实现自定义对话框的返回值,使用
- 语言是信息传播的主要障碍。多语言网站,顾名思义就是能够以多种语言(而不是单种语言)为用户提供信息服务,让使用不同语言的用户都能够从同个网站获
- 本文实例讲述了Go语言实现的web爬虫方法。分享给大家供大家参考。具体分析如下:这里使用 Go 的并发特性来并行执行 web 爬虫。修改 C
- 用Python基于Google Bard做一个交互式的聊天机器人之前已经通过浏览器试过了 Google Bard ,更多细节请看: Try
- 用selenium做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击、双击、点击鼠标右键、拖拽等等。而selenium给我们提供
- 本文实例为大家分享了python实现图片批量压缩程序的具体代码,供大家参考,具体内容如下说明运行环境:Win10 Pycharm
- 本文实例讲述了Smarty实现页面静态化(生成HTML)的方法。分享给大家供大家参考,具体如下:为了减少数据库读取次数,某些内容不经常被更改
- 前言最近将使用爬虫爬取的链接保存到 mysql 数据库中时,发现我将链接使用 json_encode 保存时候,在数据库中却显示了转义字符,