Dojo follows theAsynchronous Module Definition style which is self-speaking.
1.Logic in the define method;
define method is the function in the dojo base which is located in dojo.js. The statements are as following which comply with AMD API:
var def = function( mid,//(commonjs.moduleId,optional) list of modules to be loaded before running factory dependencies,//(array of commonjs.moduleId,optional) factory //(any) ){ /// // Advises the loader of a module factory. //Implements http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition. /// //note // CommonJS factory scan courtesy of http://requirejs.org var arity = arguments.length,defaultDeps = ["require","exports","module"],// the predominate signature... args = [0,mid,dependencies]; if(arity==1){ args = [0,(isFunction(mid) ? defaultDeps : []),mid]; }else if(arity==2 && isString(mid)){ args = [mid,(isFunction(dependencies) ? defaultDeps : []),dependencies]; }else if(arity==3){ args = [mid,dependencies,factory]; } if(has("dojo-amd-factory-scan") && args[1]===defaultDeps){ args[2].toString() .replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,"") .replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g,function(match,dep){ args[1].push(dep); }); } req.trace("loader-define",args.slice(0,2)); var targetModule = args[0] && getModule(args[0]),module; if(targetModule && !waiting[targetModule.mid]){ // given a mid that hasn't been requested; therefore,defined through means other than injecting // consequent to a require() or define() application; examples include defining modules on-the-fly // due to some code path or including a module in a script element. In any case,// there is no callback waiting to finish processing and nothing to trigger the defQ and the // dependencies are never requested; therefore,do it here. injectDependencies(defineModule(targetModule,args[1],args[2])); }else if(!has("ie-event-behavior") || !has("host-browser") || injectingCachedModule){ // not IE path: anonymous module and therefore must have been injected; therefore,onLoad will fire immediately // after script finishes being evaluated and the defQ can be run from that callback to detect the module id defQ.push(args); }else{ // IE path: possibly anonymous module and therefore injected; therefore,cannot depend on 1-to-1,// in-order exec of onLoad with script eval (since it's IE) and must manually detect here targetModule = targetModule || injectingModule; if(!targetModule){ for(mid in waiting){ module = modules[mid]; if(module && module.node && module.node.readyState === 'interactive'){ targetModule = module; break; } } if(has("dojo-combo-api") && !targetModule){ for(var i = 0; i<combosPending.length; i++){ targetModule = combosPending[i]; if(targetModule.node && targetModule.node.readyState === 'interactive'){ break; } targetModule= 0; } } } if(has("dojo-combo-api") && isArray(targetModule)){ injectDependencies(defineModule(getModule(targetModule.shift()),args[2])); if(!targetModule.length){ combosPending.splice(i,1); } }else if(targetModule){ consumePendingCacheInsert(targetModule); injectDependencies(defineModule(targetModule,args[2])); }else{ signal(error,makeError("ieDefineFailed",args[0])); } checkComplete(); } };2.Logic in the declare method
declare is defined in the dojo/_base/declare.js
function declare(className,superclass,props){ // crack parameters if(typeof className != "string"){ props = superclass; superclass = className; className = ""; } props = props || {}; var proto,i,t,ctor,name,bases,chains,mixins = 1,parents = superclass; // build a prototype if(opts.call(superclass) == "[object Array]"){ // C3 MRO bases = c3mro(superclass,className); t = bases[0]; mixins = bases.length - t; superclass = bases[mixins]; }else{ bases = [0]; if(superclass){ if(opts.call(superclass) == "[object Function]"){ t = superclass._Meta; bases = bases.concat(t ? t.bases : superclass); }else{ err("base class is not a callable constructor.",className); } }else if(superclass !== null){ err("unknown base class. Did you use dojo.require to pull it in?",className); } } if(superclass){ for(i = mixins - 1;; --i){ proto = forceNew(superclass); if(!i){ // stop if nothing to add (the last base) break; } // mix in properties t = bases[i]; (t._Meta ? mixOwn : mix)(proto,t.prototype); // chain in new constructor ctor = new Function; ctor.superclass = superclass; ctor.prototype = proto; superclass = proto.constructor = ctor; } }else{ proto = {}; } // add all properties declare.safeMixin(proto,props); // add constructor t = props.constructor; if(t !== op.constructor){ t.nom = cname; proto.constructor = t; } // collect chains and flags for(i = mixins - 1; i; --i){ // intentional assignment t = bases[i]._Meta; if(t && t.chains){ chains = mix(chains || {},t.chains); } } if(proto["-chains-"]){ chains = mix(chains || {},proto["-chains-"]); } // build ctor t = !chains || !chains.hasOwnProperty(cname); bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) : (bases.length == 1 ? singleConstructor(props.constructor,t) : chainedConstructor(bases,t)); // add Meta information to the constructor ctor._Meta = {bases: bases,hidden: props,chains: chains,parents: parents,ctor: props.constructor}; ctor.superclass = superclass && superclass.prototype; ctor.extend = extend; ctor.createSubclass = createSubclass; ctor.prototype = proto; proto.constructor = ctor; // add "standard" methods to the prototype proto.getInherited = getInherited; proto.isInstanceOf = isInstanceOf; proto.inherited = inheritedImpl; proto.__inherited = inherited; // add name if specified if(className){ proto.declaredClass = className; lang.setObject(className,ctor); } // build chains and add them to the prototype if(chains){ for(name in chains){ if(proto[name] && typeof chains[name] == "string" && name != cname){ t = proto[name] = chain(name,chains[name] === "after"); t.nom = name; } } } // chained methods do not return values // no need to chain "invisible" functions return ctor; // Function }