declare接口是dojo定義類系統的關鍵函數, 類系統就是抽象,封裝,繼承.dojo用javascript的prototype實現繼承, 用mixin實現派生, javascript一切都是函數, 這自己就是高度抽象.巧妙的地方在於: 對於一個類, 有構造函數和類名字, 實際上構造函數是用戶自定義的函數, 類名字也是用戶自定的, 怎麼實現用戶使用new操做符的時候, 構造整個對象呢?javascript
好比, Dialog.js裏聲明瞭一個dijit.Dialog, 這是一個var,仍是一個函數?實際上, 在declare接口裏:java
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).app
declare接口裏:函數
768 // chain in new constructor
769 ctor = new Function;
770 ctor.superclass = superclass;
771 ctor.prototype = proto;
772 superclass = proto.constructor = ctor;
ctor首先是一個匿名函數, 接下來的post
799 bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
800 (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
實際上給ctor賦值了simpleConstructor或者chainedConstructor的返回值, 而好比this
simpleConstructor的返回值是個函數:spa
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是一個函數, 函數體裏 :prototype
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;orm
也就是當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.