CMD用法//sea.jsdefine('a',function(require,exports,module){console.log('aload');exports.run=function(){console.log('arun')}})define('b',function(require,exports,module){console.log('bload');exports.run=function(){console.log('brun')}})define('main',function(require,exports,module){console.log('mainrun');vara=require('a');a.run();varb=require('b');b.run();})seajs.use('main');//mainrun//aload//arun//bload//brunseajs简单实现constmodules={};constexports={};constsj={}//获取地址//dep->a->a.js->http:xxx/xx/xx/a.jsconst__getUrl=(dep)=>{constp=location.pathname;returnp.slice(0,p.lastIndexOf('/'))+'/'+dep+'js';}//普通scriptconst__load=(url)=>{returnnewPromise((resolve,reject)=>{constheader=document.getElementsByTagName("标题")[0];constscript=document.createElement('脚本');script.async=true;脚本.src=url;script.type='文本/javascript';script.onload=解析;script.onerror=拒绝;header.appendChild(脚本);})}const__getDepsFromFn=(fn)=>{让匹配=[];//require('a')//(?:require\()->require((?:)非捕获分组//(?:['"])->require('//([^'"]+)->避免回溯->回溯状态机letreg=/(?:require\()(?:['"])([^'"]+)/gletr=null;while((r=reg.exec(fn.toString()))!==null){reg.lastIndex;matches.push(r[1])}returnmatches;}//依赖关系如何?//提取依赖关系:1.正则表达式2.状态机constdefine=(id,factory)=>{consturl=__getUrl(id);constdeps=__getDepsFromFn(factory);if(!modules[id]){modules[id]={url,id,factory,deps};}}const__exports=(id)=>exports[id]||(exports[id]={});const__module=this;//只有这里是加载模块的地方//这种写法是promise,所以需要在vara=require('a')__require=(id)=>{return__load(__getUrl(id)).then(()=>{//加载后const{factory,deps}=modules[id];if(!deps||deps.length==0){factory(__require,__exports(id),__module);return__exports(id);}})}sj.use=(mods,callback)=>{mods=Array.isArray(mods)?模组:[模组];returnnewPromise((resolve,reject)=>{Promise.all(mods.map(mod=>{return__load(__getUrl(mod)).then(()=>{//加载后const{factory}=modules[mod];factory(__require,__exports(mod),__module);return__exports(mod);})})).then(resolve,reject);}).then(instance=>callback&&callback(...实例));}
