dojo分析之declare接口
declare接口是dojo定义类系统的关键函数, 类系统就是抽象,封装,继承.dojo用javascript的prototype实现继承, 用mixin实现派生, javascript一切都是函数, 这本身就是高度抽象.巧妙的地方在于: 对于一个类, 有构造函数和类名字, 实际上构造函数是用户自定义的函数, 类名字也是用户自定的, 怎么实现用户使用new操作符的时候, 构造整个对象呢?
1. 对象从哪来
比如, Dialog.js里声明了一个dijit.Dialog, 这是一个var,还是一个函数?实际上, 在declare接口里:
817 // add name if specified
818 if(className){
819 proto.declaredClass = className;
820 lang.setObject(className, ctor);
821 }
红 字部分, 把dijit.Dialog声明成了一个对象, 并且赋值为ctor, 实际上ctor是一个函数, 马上就说会说到. 当new操作的时候, 实际上调用的是ctor这个函数, 这个函数并不是dijit.Dialog里constructor(继承_Widget.js).
2. 关联类名字的函数ctor
declare接口里:
768 // chain in new constructor
769 ctor = new Function;
770 ctor.superclass = superclass;
771 ctor.prototype = proto;
772 superclass = proto.constructor = ctor;
ctor首先是一个匿名函数, 接下来的
799 bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
800 (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
实际上给ctor赋值了simpleConstructor或者chainedConstructor的返回值, 而比如
simpleConstructor的返回值是个函数:
441 // plain vanilla constructor (can use inherited() to call its base constructor)
442 function simpleConstructor(bases){
443 return function(){
444 var a = arguments, i = 0, f, m;
445
446 if(!(this instanceof a.callee)){
447 // not called via new, so force it
448 return applyNew(a);
449 }
450
451 //this._inherited = {};
452 // perform the shaman's rituals of the original declare()
453 // 1) do not call the preamble
454 // 2) call the top constructor (it can use this.inherited())
455 for(; f = bases[i]; ++i){ // intentional assignment
456 m = f._meta;
457 f = m ? m.ctor : f;
458 if(f){
459 f.apply(this, a);
460 break;
461 }
462 }
463 // 3) call the postscript
464 f = this.postscript;
465 if(f){
466 f.apply(this, a);
467 }
468 };
469 }
也就是ctor = 441 // plain vanilla constructor (can use inherited() to call its base constructor)
442 function simpleConstructor(bases){
443 return function(){
444 var a = arguments, i = 0, f, m;
445
446 if(!(this instanceof a.callee)){
447 // not called via new, so force it
448 return applyNew(a);
449 }
450
451 //this._inherited = {};
452 // perform the shaman's rituals of the original declare()
453 // 1) do not call the preamble
454 // 2) call the top constructor (it can use this.inherited())
455 for(; f = bases[i]; ++i){ // intentional assignment
456 m = f._meta;
457 f = m ? m.ctor : f;
458 if(f){
459 f.apply(this, a);
460 break;
461 }
462 }
463 // 3) call the postscript
464 f = this.postscript;
465 if(f){
466 f.apply(this, a);
467 }
468 };
469 }
也就是ctor是一个函数, 函数体里 :
455 for(; f = bases[i]; ++i){ // intentional assignment
456 m = f._meta;
457 f = m ? m.ctor : f;
458 if(f){
459 f.apply(this, a);
460 break;
也就是当new调用这个对应dijit.Dialog的ctor的时候, 会执行_meta.ctor, 实际就是声明里边的constructor, 之后又调用:
463 // 3) call the postscript
464 f = this.postscript;
465 if(f){
466 f.apply(this, a);
467 }
3. 总结
declare接口, 声明一个类, 实际上就是定一个了一个xxxx.xxxx.xxx这样的名字的一个函数, 名字就是类名, 函数就是调用constructor和postscript两个回调的ctor.
当, new的时候, xxx.xxx.xxx被调用, 近而调用了constructor和postscript函数.
需要理解具体的构造过程的话, 需要关注 : simpleConstructor和chainedConstructor.
dojo分析之declare接口的更多相关文章
- Dojo的declare接口
declare(classname,[],{}) declare的第一个参数是可选的,代表类的名称 declare的第二个参数代表类的继承关系,比如继承哪一个父类,可以看到:第二个参数是一个数组,所以 ...
- mybatis源码分析之04Mapper接口的动态代理
在工作中,使用mybatis操作数据库,只需要提供一个接口类,定义一些方法,然后调用接口里面的方法就可以CRUD,感觉是牛了一逼! 该篇就是记录一下,mybatis是如何完成这波骚操作的,即分析我们测 ...
- MyBatis 源码分析——生成Statement接口实例
JDBC的知识对于JAVA开发人员来讲在简单不过的知识了.PreparedStatement的作用更是胸有成竹.我们最常见用到有俩个方法:executeQuery方法和executeUpdate方法. ...
- 【spring源码分析】BeanDefinitionRegistryPostProcessor接口可自定义bean加入IOC
自定义BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcesso ...
- 后端程序员之路 33、Index搜索引擎实现分析2-对外接口和大体流程
# index_manager的单例是index server对外的唯一接口,part_indexer是index搜索的核心部分,index_manager持有了一组part_indexer. typ ...
- Dojo Data Store——统一数据访问接口
原文地址:http://www.infoq.com/cn/articles/wq-dojo-data-store 无论在传统的桌面应用还是在主流的互联网应用中,数据始终占据着软件应用中的核心地位.当下 ...
- List 接口以及实现类和相关类源码分析
List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...
- 【Spring源码分析系列】ApplicationContext 相关接口架构分析
[原创文章,转载请注明出处][本文地址]http://www.cnblogs.com/zffenger/p/5813470.html 在使用Spring的时候,我们经常需要先得到一个Applicati ...
随机推荐
- svn ignore
工程名为simple,采用maven进行依赖管理,在check in时我不想工程下maven产生的target目录被提交到SVN(包括目录下所有文件和目录本身). 解决方法: 要被忽略的目录必须是未版 ...
- Winform主窗体设计
主窗体顶部为菜单按钮,子窗体内嵌入Panel显示 界面如下: 第二步,主窗体离不开的几个方法 1,点击菜单功能,加载子窗体 private void btnOpenForm_Click(object ...
- 查看应用程序使用的所有dll
VS2008命令提示符下: >dumpbin.exe /dependents <文件路径+文件名> □
- 利用chrome的profiler查找js的memory leak
1. 首先要固定一个测试环境.具体来说,选择某一个可以重复的操作,作为标准的测试动作. 2. 刷新浏览器后用profiler抓下heap snapshot. 3. 进行操作,再一次抓下snapshot ...
- js常用的地址栏参数获取
用JS获取地址栏参数的方法(超级简单) 方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!) function GetQueryString(name) { var reg ...
- iOS基础之网络请求相关
1.AFNetwork二次封装方法一: #import <Foundation/Foundation.h> @interface BeeNetworkManager : NSObject ...
- 【洛谷P1196】银河英雄传说
有特殊意义的一道题-- 加权并查集,我们增加cnt.deep数组 分别表示i点所在链共有多少个点,以及路径压缩之前点i在链中的深度 每次合并时直接修改cnt,路径压缩的同时更新deep 因为每次查询之 ...
- MATLAB-octave中向量场图的可视化
参考http://379910987.blog.163.com/blog/static/33523797201162223310546/ 设二维函数z=f(x,y),其中z为海拔,x为东西测向距离而y ...
- Python垃圾回收机制
引用计数Python默认的垃圾收集机制是“引用计数”,每个对象维护了一个ob_ref字段.它的优点是机制简单,当新的引用指向该对象时,引用计数 引用计数 Python默认的垃圾收集机制是“引用计数”, ...
- step by step 之餐饮管理系统六(数据库访问模块)
距上次写的博客已经好几个月,一方面公司里面有很多的东西要学,平时的时候又要写代码,所以没有及时更新,不过现在还好,已经成型了,现在把之前的东西贴出来,先看一下现在做的几个界面吧.第一个界面是用颜色用区 ...