`
子衿青青
  • 浏览: 105500 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

dojo类机制实现原理分析

 
阅读更多

前段时间曾经在InfoQ中文站上发表文章,介绍了dojo类机制的基本用法。有些朋友在读后希望能够更深入了解这部分的内容,本文将会介绍dojo类机制幕后的知识,其中会涉及到dojo类机制的实现原理并对一些关键方法进行源码分析,当然在此之前希望您能够对JavaScript和dojo的使用有些基本的了解。

dojo的类机制支持类声明、继承、调用父类方法等功能。dojo在底层实现上是通过操作原型链来实现其类机制的,而在实现继承时采用类式继承的方式。值得一提的是,dojo的类机制允许进行多继承(注意,只有父类列表中的第一个作为真正的父类,其它的都是将其属性以mixin的方法加入到子类的原型链中),为解决多重继承时类方法的顺序问题,dojo用JavaScript实现了Python和其它多继承语言所支持的C3父类线性化算法,以实现线性的继承关系,想了解更多该算法的知识,可参考这里,我们在后面的分析中将会简单讲解dojo对此算法的实现。

1. dojo类声明概览

dojo类声明相关的代码位于“/dojo/_base/declare.js”文件中,定义类是通过dojo.declare方法来实现的。关于这个方法的基本用法,已经在dojo类机制简介这篇文章中进行了阐述,现在我们看一下它的实现原理(在这部分的代码分析中,会在整体上介绍dojo如何声明类,后文会对里面的重要细节内容进行介绍):


以上简单介绍了dojo声明类的整体流程,但是一些关键的细节如C3算法、链式调用在后面会继续进行介绍。

2. C3算法的实现

通过以前的文章和上面的分析,我们知道dojo的类声明支持多继承。在处理多继承时,不得不面对的就是继承链如何构造,比较现实的问题是如果多个父类都拥有同名的方法,那么在调用父类方法时,要按照什么规则确定调用哪个父类的呢?在解决这个问题上dojo实现了C3父类线性化的方法,对多个父类进行合理的排序,从而完美解决了这个问题。

为了了解继承链的相关知识,我们看一个简单的例子:


以上的代码中,声明了几个类,通过C3算法得到G的继承顺序应该是这样G->E->C->D->B->A的,只有按照这样的顺序才能保证类定义和依赖是正确的。那我们看一下这个C3算法是如何实现的呢:


通过以上的分析,我们可以看到,这个算法实现起来相当复杂,如果朋友们对其感兴趣,建议按照上文的例子,自己加断点进行调试分析。dojo的作者使用了不到100行的代码实现了这样强大的功能,里面有很多值得借鉴的设计思想。


3. 链式构造器的实现

在第一部分代码分析中我们曾经看到过定义构造函数的代码,如下:


这个方法对于理解dojo类机制很重要。从前一篇文章的介绍中,我们了解到默认情况下,如果dojo声明的类存在继承关系,那么就会自动调用父类的构造方法,且是按照继承链的顺序先调用父类的构造方法,但是从1.4版本开始,dojo提供了手动设置构造方法调用的选项。在以上的代码中涉及到dojo声明类的三个方法,如果该类没有父类,那么调用的就是singleConstructor,如果有父类的话,那么默认调用的是chainedConstructor,如果手动设置了构造方法,那么调用的就是simpleConstructor,要启动这个选项只需在声明该类的时候添加chains的constructor声明即可。


比方说,我们在定义继承自com.levinzhang.Person的com.levinzhang.Employee类时,可以这样做:


添加以上代码后,在构造com.levinzhang.Employee实例时,就不会再调用所有父类的构造方法了,但是此时我们可以使用inherited方法显式的调用父类方法。


限于篇幅,以上的三个方法不全部介绍,只介绍chainedConstructor的核心实现:

4. 调用父类方法的实现

在声明dojo类的时候,如果想调用父类的方法一般都是通过使用inherited方法来实现,但从1.4版本开始,dojo支持链式调用所有父类的方法,并引入了一些AOP的概念。我们将会分别介绍这两种方式。

1) 通过inherited方式调用父类方法

在上一篇文章中,我们曾经介绍过,通过在类中使用inherited就可以调用到。这里我们要深入inherited的内部,看一下其实现原理。因为inherited支持调用父类的一般方法和构造方法,两者略有不同,我们关注调用一般方法的过程。


2) 链式调用父类方法

这是从dojo 1.4版本新加入的功能。如果在执行某个方法时,也想按照一定的顺序执行父类的方法,只需在定义类时,在-chains-属性中加以声明即可。


添加了以上声明后,意味着Employee及其所有的子类,在调用sayMyself方法时,都会先调用本身的同名方法,然后再按照继承链依次调用所有父类的同名方法,我们还可以将值“before”替换为“after”,其执行顺序将会相反。在-chains-属性中声明的方法,在类定义时,会进行特殊处理,正如我们在第一章中看到的那样:


我们可以看到在-chains-中声明的方法都进行了替换,换成了chain方法的返回值,而这个方法也比较简单,源码如下:

5. 工具方法和属性如isInstanceOf、declaredClass的实现

除了上面提到的inherited方法以外,dojo在实现类功能的时候,还实现了一些工具方法和属性,这里介绍一个方法isInstanceOf和一个属性declaredClass。从功能上来说isInstanceOf方法用来判断一个对象是否为某个类的实例,而declaredClass属性得到的是某个对象所对应声明类的名字。


而declaredClass属性的实现比较简单,只是在声明类的原型上添加了一个属性而已,类的实例对象就可以访问这个属性得到其声明类的名字了。这段代码在dojo.declare方法中:


在dojo实现类机制的过程中,有一些内部的方法,是很值得借鉴的如forceNew、safeMixin等,这些方法在实现功能的同时,保证了代码的高效执行,感兴趣的朋友可以进一步的研究。

6. 总结与思考

1) dojo在实现类机制方面支持多继承方式,其它JavaScript类库中很少能做到,而利用JavaScript原生语法实现多继承也较为困难。在这一点上dojo的类机制的功能确实足够强大。但是多继承会增加编码的难度,对开发人员如何组织类也有更高的要求;

2) 链式调用父类方法时,我们可以看到dojo引入了许多AOP的理念,在1.7的版本中,将会有单独的模块提供AOP相关的支持,我们将会持续关注类似的功能;

3) 在dojo的代码中,多处都会出现方法替换,如链式方法调用、事件绑定等,这种设计思想值得我们关注和学习;

4) 使用了许多的内部属性,如_meta、bases等,这些元数据在实现复杂的类机制中起到了至关重要的作用,在进行源码分析的时候,我们可以给予关注,如果要实现类似功能也可以进行借鉴。

探究类库的实现原理是提高自己编码水平的好办法,类似于dojo这样类库的核心代码基本上每一行都有其设计思想在里面(当然也不可以盲目崇拜),每次阅读和探索都会有所发现和心得,当然里面肯定也会有自以为是或谬误之处,在此很乐意和读到这篇文章的朋友们一起研究,欢迎批评指正。

参考资料:

http://docs.dojocampus.org/

http://blog.csdn.net/dojotoolkit/

http://dojotoolkit.org/

作者信息:张卫滨,关注企业级Java开发和RIA技术,个人博客:http://lengyun3566.iteye.com,微博:http://weibo.com/zhangweibin1981

声明:
  本文已经首发于InfoQ中文站,版权所有,原文为《dojo类机制实现原理分析》,如需转载,请务必附带本声明,谢谢。
  InfoQ中文站是一个面向中高端技术人员的在线独立社区,为Java、.NET、Ruby、SOA、敏捷、架构等领域提供及时而有深度的资讯、高端技术大会如QCon 、线下技术交流活动QClub、免费迷你书下载如《架构师》等。

分享到:
评论

相关推荐

    dojo的包加载机制

    dojo的包加载机制, 源代码中加了注释和debug,只供大家参考

    dojo dojo实例 dojo例子 dojo资料 dojo项目 dojo实战 dojo模块 dojo编程

    dojo dojo实例 dojo例子 dojo资料 dojo项目 dojo实战 dojo模块 dojo编程

    AJAX之Dojo实现登陆框

    AJAX之Dojo实现登陆框

    DOJO TableContainer实现表单布局.js

    DOJO TableContainer实现表单布局.js

    dojo enhancedGrid pagination 分页实现

    利用dojo的enhancedGrid实现分页,利用静态数据加载和json文件方式分别加载,也利用XHR方式获取json文件数据生成grid,另外利用fetch实现分页的过滤、排序等功能。

    DOJO 学习笔记 dojo

    一、 Dojo学习笔记(1. 模块与包) 1 二、 Dojo学习笔记(2. djConfig解说) 4 三、 Dojo学习笔记(3. Dojo的基础对象和方法) 6 四、 Dojo学习笔记(4. dojo.string & dojo.lang) 9 五、 Dojo学习笔记(5. dojo.lang.array ...

    dojo文档 dojo文档 dojo文档

    dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档 dojo文档

    dojo实现登陆框架

    dojo 实现登陆框架 浪曦的那个谁讲的我忘了饿

    dojo js dojo js

    dojo js dojo js dojo js dojo js dojo js dojo js dojo js

    精通Dojo by Dojo之父

    Dojo是一个非常强大的、面向对象的、开源的JavaScript工具箱,它为开发富客户端Ajax...学习完本书后,读者不仅能熟悉Dojo框架的使用,还能了解Ajax框架的工作原理,最重要的是,还能随心所欲地开发出自己的RIA应用。

    DOJO中文手册【出自dojo中国】

    Dojo 是一个用javascript语言实现的开源DHTML工具包。它是在几个项目捐助基础上建立起来的(nWidgets, Burstlib, f(m)), 这也是为什么叫它a \"unified\" toolkit的原因。Dojo的目标是解决开发DHTML应用程序遇到的那些...

    定义自己的dojo组件类

    该文档教大家如何定义自己的dojo组件类,并在程序中如何引用

    struts2+dojo实现例子

    struts2+dojo ajax实现小例子,部署后可直接使用,可供学习和参考。

    dojo精品中文教程(包一)

    很不错的中文教程!文件太大分3个包! 目录如下: dojo精品中文教程 Dojo.1.0 Practice Note [1] 什么是dojo 选择dojo的理由 AJAX架构之Dojo篇 Adding Ajax中文版 (DoJo) ...利用Dojo实现拖动(Drag and Drop)效果

    dojo精品中文教程(全)

    分三个包上传时,第三个包好像传不上去,我给整合了一下,打在一个包里上传了! dojo精品中文教程 Dojo.1.0 Practice Note [1] 什么是dojo 选择dojo的理由 ...利用Dojo实现拖动(Drag and Drop)效果

    javascript dojo

    学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源学习dojo的绝好资源...

    Dojo.js核心dojo的javaScript类库Dojo.js核心dojo的javaScript类库Dojo.js核心dojo的javaScript类库

    dojo.js.核心jsDojo.js核心dojo的javaScript类库Dojo.js核心dojo的javaScript类库Dojo.js核心dojo的javaScript类库Dojo.js核心dojo的javaScript类库

    dojo入门系列教程.rar

    dojo入门系列教程,包含入门简介,在javascript基础上介绍dojo的语法特色,ajax的dojo包装---xhr框架的编程要点, Dojo 事件机制.以及对dojo最具特色的web UI设计的全面介绍.

    dojo精品中文教程(包二)

    很不错的中文教程!文件太大分3个包! 目录如下: dojo精品中文教程 Dojo.1.0 Practice Note [1] 什么是dojo 选择dojo的理由 AJAX架构之Dojo篇 Adding Ajax中文版 (DoJo) ...利用Dojo实现拖动(Drag and Drop)效果

Global site tag (gtag.js) - Google Analytics