摘要:怎样才算更好不用依赖注入不用写,自动匹配依赖如下所示这就要借助能力,把的字符串替换成带有就可以实现上面的效果。再也不用区分循环依赖和非循环依赖了上面的所有代码可以上找到
回顾
上篇文章大概展示了kmdjs0.1.x时期的编程范式:
如下面所示,可以直接依赖注入到function里,
kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function(bom,Ball,test) { var ball = new Ball(0, 0, 28, 1, -2, "kmdjs"); var vp = bom.getViewport(); });
也可以直接在代码里把full namespace加上来调用,如:
kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function() { var ball = new app.Ball(0, 0, 28, 1, -2, "kmdjs"); var vp = util.bom.getViewport(); });
而且,在循环依赖的场景,因为执行顺序的问题,会导致第一种方式注入undefined,所以循环依赖的情况下只能用full namespace的方式来调用。
这种编程体验虽然已经足够好,但是可以更好。怎样才算更好?
不用依赖注入function
不用写full namespace,自动匹配依赖
如下所示:
kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function() { var ball = new Ball(0, 0, 28, 1, -2, "kmdjs"); var vp = bom.getViewport(); });
这就要借助uglifyjs能力,把function的字符串替换成带有namespace就可以实现上面的效果。
uglifyjs依赖分析和代码重构function fixDeps(fn,deps) { var U2 = UglifyJS; //uglify2不支持匿名转ast var code = fn.toString().replace("function","function ___kmdjs_temp"); var ast = U2.parse(code); ast.figure_out_scope(); var nodes = []; ast.walk(new U2.TreeWalker(function (node) { if (node instanceof U2.AST_New) { var ex = node.expression; var name = ex.name; isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(ex.scope, name) || nodes.push({name:name,node:node}); } if (node instanceof U2.AST_Dot) { var ex = node.expression; var name = ex.name; var scope = ex.scope; if (scope) { isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(ex.scope, name) || nodes.push({name:name,node:node}); } } if (node instanceof U2.AST_SymbolRef) { var name = node.name; isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(node.scope, name) || nodes.push({name:name,node:node}); } })); var cloneNodes = [].concat(nodes); //过滤new nodes 中的symbo nodes for (var i = 0, len = nodes.length; i < len; i++) { var nodeA = nodes[i].node; for (var j = 0, cLen = cloneNodes.length; j < cLen; j++) { var nodeB = cloneNodes[j].node; if (nodeB.expression === nodeA) { nodes.splice(i, 1); i--; len--; } } } for (var i = nodes.length; --i >= 0;) { var item = nodes[i], node=item.node, name=item.name; var fullName=getFullName(deps,name); var replacement; if (node instanceof U2.AST_New) { replacement = new U2.AST_New({ expression: new U2.AST_SymbolRef({ name:fullName }), args: node.args }); } else if (node instanceof U2.AST_Dot) { replacement = new U2.AST_Dot({ expression: new U2.AST_SymbolRef({ name: fullName }), property: node.property }); }else if(node instanceof U2.AST_SymbolRef){ replacement = new U2.AST_SymbolRef({ name: fullName }); } var start_pos = node.start.pos; var end_pos = node.end.endpos; code = splice_string(code, start_pos, end_pos, replacement.print_to_string({ beautify: true })); } return code.replace("function ___kmdjs_temp","function"); } function getFullName(deps,name){ var i= 0, len=deps.length, matchCount= 0, result=[]; for(;i1){ throw "the same name conflict: "+result.join(" and "); } else if(matchCount===1){ return result[0]; }else{ throw " can not find module ["+name+"]"; } } function splice_string(str, begin, end, replacement) { return str.substr(0, begin) + replacement + str.substr(end); } function isInScopeChainVariables(scope, name) { var vars = scope.variables._values; if (Object.prototype.hasOwnProperty.call(vars, "$" + name)) { return true; } if (scope.parent_scope) { return isInScopeChainVariables(scope.parent_scope, name); } return false; } function isInArray(arr,name){ var i= 0,len=arr.length; for(;i 通过上面的fixDeps,可以对代码就行变换。如:
console.log(fixDeps(function (A) { var eee = m; var b = new A(); var b = new B(); var c = new C(); var d = G.a; },["c.B","AAA.G","SFSF.C","AAAA.m"] ))输出:
function (A) { var eee = AAAA.m; var b = new A(); var b = new c.B(); var c = new SFSF.C(); var d = AAA.G.a; }这样,kmdjs在执行模块function的时候,只需要fixDeps加上full namespace就行:
function buildBundler(){ var topNsStr = ""; each(kmdjs.factories, function (item) { nsToCode(item[0]); }); topNsStr+= kmdjs.nsList.join(" ") +" "; each(kmdjs.factories, function (item) { topNsStr+=item[0]+" = ("+ fixDeps(item[2],item[1])+")(); " ; }); if(kmdjs.buildEnd) kmdjs.buildEnd(topNsStr); return topNsStr; }build出来的包,当然全都加上了namespace。再也不用区分循环依赖和非循环依赖了~~~
Github上面的所有代码可以Github上找到:
https://github.com/kmdjs/kmdjs
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79667.html
摘要:华三通信云计算产品线总裁吴健这样说到。虽然低调如斯,但这丝毫没有影响华三通信在云计算领域内的江湖地位。相比起来,华三通信发布的超融合系统产品则更加广为人知。 从引力波到AlphaGo,从虚拟现实到新能源,从电子政务到云课堂,云计算早已不再是高高在上的概念,而是已经渗透到了科技、工作、生活的每一个角落。 云计算的大行其道,不但改变了科技行业原有的技术路线,更是改变了既有的产业格局,创新、融...
摘要:从很早的版本就开始,是支持循环依赖的。比如下面的代码会被编译成要支持循环依赖其实有个要求,就是。不是的循环依赖是无解的循环依赖。所以在初始化阶段,这样的循环依赖是被允许的,因为都是。 循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚。所以没解决好循环依赖的模块化库、框架、编译器都不是一个好库、...
阅读 1471·2021-11-24 09:38
阅读 3350·2021-11-18 10:02
阅读 3229·2021-09-22 15:29
阅读 2920·2021-09-22 15:15
阅读 1006·2021-09-13 10:25
阅读 1800·2021-08-17 10:13
阅读 1919·2021-08-04 11:13
阅读 1958·2019-08-30 15:54