• dojo分析之declare接口


    欢迎转载opendevkit文章, 文章原始地址: http://www.opendevkit.com/?e=57

    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.
  • 相关阅读:
    Socket和数据库的一些使用---郭雪彬
    懒加载--初步理解. by:王朋
    自定义带图片和文字的Button的排版--陈棚
    一些开源库分享 ---严焕培
    实现“手机qq”侧滑菜单 -- 吴欧
    iOS 小技巧总结
    Responder一点也不神秘————iOS用户响应者链完全剖析 周傅琦君
    通过版本号来判断用户是否是第一次登陆----By张秀清
    常用第三方推荐
    static, const 和 static const 变量的初始化问题
  • 原文地址:https://www.cnblogs.com/linucos/p/3825031.html
Copyright © 2020-2023  润新知