declare接口是dojo定义类系统的关键函数, 类系统就是抽象,封装,继承.dojo用javascript的prototype实现继承, 用mixin实现派生, javascript一切都是函数, 这本身就是高度抽象.巧妙的地方在于: 对于一个类, 有构造函数和类名字, 实际上构造函数是用户自定义的函数, 类名字也是用户自定的, 怎么实现用户使用new操作符的时候, 构造整个对象呢?
比如, 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).
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 }
declare接口, 声明一个类, 实际上就是定一个了一个xxxx.xxxx.xxx这样的名字的一个函数, 名字就是类名, 函数就是调用constructor和postscript两个回调的ctor.
当, new的时候, xxx.xxx.xxx被调用, 近而调用了constructor和postscript函数.
需要理解具体的构造过程的话, 需要关注 : simpleConstructor和chainedConstructor.转载于:https://www.cnblogs.com/linucos/p/3825031.html
