有人说js中有三座大三:this、原型链和scope tree,搞懂了他们就算是js成人礼。当然还有其他不同看法的js成人礼,如熟悉js的:OOP、AP、FP、DOP、AOP。当然还听说一种最牛B的js成人礼:熟悉jQuery……=   =!因为$里面可以放下全世界,比如$(“全世界”)…

这篇文章主要讲KMDjs利用Uglify2去分析出一个函数的所有依赖,之后才能正确地加载相关的js文件。该文涉及到js中三座大山中的scope tree….先看下面这段程序:

function test() {var user = new User();
}

很显然,该函数依赖User。我一定要去加载User.js才能正确执行该函数。那么我是不是可以写一段非常牛B的正则找到new  和()之间的User。当然,这样一定是不对的,因为js里创建对象的实例可以省略括号,比如:

function test() {var user = new User;
}

那么,是不是可以写一段非常牛B的正则,去查找new与分号之间的东西?相对于这个函数,是可以的!但是如果,这个函数长成这个样子:

function test(User) {var user = new User;
}

可以看得到,该函数不依赖任何对象,User是test的参数传递进来…,那么我是不是可以写一段非常牛B的正则,先找到test(User)中的User参数,然后再通过正则找到new后面的所有对象,最后把第二次查找到的结果过滤掉第一次查找到的参数。好问题来了,如果程序长这样子:

function test(User) {var xxx = "(User)";var user = new User;
}

可能有人会说了,只能说明你的正则不牛B。牛B的正则是可以确认是字符串中的,还是非字符串中的。那么再看下一段程序:

function test() {var User = function (name) {this.name = name;}var u = new User();
}

可以看得出,User根本不是参数,而是直接在test内部定义!那么这个函数其实是不依赖User。那么,刚刚憋出的两段牛B的正则就彻底废掉了。再比如:

function test() {var vp = Bom.getViewport();
}

可以看到,直接访问Bom的静态方法,都不需要new,就能访问Bom下的getViewport方法。所以,该函数依赖Bom。那么,刚刚憋出的两段牛B的正则再次彻底废掉了。再比如:

function test() {var vp = new Array();var el = document.getElementById("xx");
}

可以发现,window下的Array和document还需要过滤掉…,再比如

function test() {var h = 1;//这里 h a 都是可以找到,不能判定为赖function a(e) {//这里面h a e i b都是可以找到,不能判定为赖var i = 2;function b(f) {//这里面h a e i b f c都是可以找到,不能判定为赖function c(g) {//这里面h a e i b f c g都是可以找到,不能判定为赖}}}
}

如上面注释所描述,会有一串scope tree。那么…怎么办?uglify2有强大无比的ast.walk和UglifyJS.TreeWalker!如:

http://lisperator.net/blog/using-uglifyjs-for-code-refactoring/

这是官方重构代码的简单例子。受此文启发,我便为kmdjs写了个完美的依赖分析:

function getRef(fn) {var U2 = UglifyJS;var ast = U2.parse(fn.toString());         ast.figure_out_scope();var result = [];ast.walk(new U2.TreeWalker(function (node) {if (node instanceof U2.AST_New) {var ex = node.expression;var name = ex.name;if (!isInScopeChainVariables(ex.scope, name)) {result.push(name);}}if (node instanceof U2.AST_Dot) {var ex = node.expression;var name = ex.name;if (!isInScopeChainVariables(ex.scope, name)) {result.push(name);}}}));return result;
}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;
}

意外惊喜,在kmdjs加入lazy(kmdjs.get)之后,lazy内部的依赖不会加载!且看下面这段代码

function test(DDDDD) {kmdjs.get("HelloKMD.Ball", function (Ball) {//因为Ball是参数,属于该scope tree中的对象,所以不依赖var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");});
}

完!

github:https://github.com/kmdjs/kmdjs

转载于:https://www.cnblogs.com/iamzhanglei/p/3841670.html

AMD and CMD are dead之KMDjs内核之依赖分析相关推荐

  1. AMD and CMD are dead之KMD.js版本0.0.2发布

    更新 正式从UglifyJS切换至UglifyJS2 增加依赖可视化功能 压缩代码更加方便 统一风格:如main的class名也不能省略 优化了kmdjs管道 修复了无数bug 通过src开启debu ...

  2. AMD and CMD are dead之js模块化黑魔法

    缘由 在2013-03-06 13:58的时候,曾甩下一片文章叫:<为什么不使用requirejs和seajs>,并放下豪言说发布一款完美的模块化库,再后来就把那篇文章删了,再然后就没有然 ...

  3. AMD and CMD are dead之KMD.js依赖可视化工具发布

    使用 require("MyAapp.DepTree", function (DepTree) {DepTree(({renderTo: "holder",wi ...

  4. 前端模块化CommonJS、AMD、CMD、ES6

    一.前端模块化 什么是模块化?为什么前端需要模块化? js代码量激增,放在同一个文件里面,不容易维护,而且牵一发而动全身. 这时候就需要将代码按照逻辑放在不同的文件里面,按照一定的语法规则,遵循特定的 ...

  5. JavaScript模块化 --- Commonjs、AMD、CMD、es6 modules

    随着前端js代码复杂度的提高,JavaScript模块化这个概念便被提出来,前端社区也不断地实现前端模块化,直到es6对其进行了规范,下面就介绍JavaScript模块化. 这篇文章还是希望能给大家一 ...

  6. 关于commonjs,AMD,CMD之间的异同

    1.简介 随着前端业务复杂度的增加,模块化成为一个大的趋势.而在ES6还未被浏览器所支持的情况下,commonjs作为ES6中标准模块加载方案,在客服端中的支持情况并不好,现在在客服端中有2中模块化的 ...

  7. node中模块、AMD与CMD、ES6模块,node中使用ES6

    1.Nodejs 中的模块 在node环境中一个js文件就是一个模块(module) 我们采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口 node的 ...

  8. 前端模块化,AMD与CMD的区别

    在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可:如今CPU.浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得 ...

  9. javascript模块化之CommonJS、AMD、CMD、UMD、ES6

    javascript模块化之CommonJS.AMD.CMD.UMD.ES6 一.总结 一句话总结: CommonJS是同步加载模块,用在服务端:AMD是异步加载模块,用于浏览器端 1.为什么服务器端 ...

  10. 理解AMD ,CMD,CommonJS规范

    https://blog.csdn.net/xcymorningsun/article/details/52709608 理解AMD ,CMD,CommonJS规范 2016年09月30日 10:33 ...

最新文章

  1. Python3.8.5最新版安装教程(含老版本卸载教程)
  2. python数据分析——世界杯分析预测
  3. 基于RDP开源许可rdesktop基本介绍
  4. attention的query、key和value的理解
  5. python 中的真值表
  6. 开放接口加密方案_27种开放式解决方案,适用于所有教育
  7. spark通过合理设置spark.default.parallelism参数提高执行效率
  8. 解决:The proxy server received an invalid response from an upstream server
  9. uc/os-II的内存改进与实现TLSF算法的详解,移植实现(三)
  10. linux解压win10iso,ISO文件的解压和WINISO問題
  11. Win7 关闭触摸屏 屏幕键盘功能
  12. Redis5.0集群搭建(三主三从)、添加一主一从、JedisCluster连接集群
  13. 21天攻克PET核心词汇,加油!
  14. ARFoundation之路-人脸检测增强之二
  15. Kaggle数据竞赛记录 - Steel Defect Detection
  16. web自动化测试之Selenium基础 — XPath定位大全
  17. C/C++模拟按键按下弹起
  18. 图像处理-sift算法
  19. vue导出excel功能实现
  20. js---函数基础练习题

热门文章

  1. TSAP(4) : 时间序列采样[asfreq( ) VS resample( )]
  2. [codeup 5038] 找零钱
  3. 容器技术Docker K8s 6 阿里云容器服务体系介绍
  4. 上验证cudnn是否安装成功_ubuntu18.04 安装cuda、cudnn、tensorflow和pytorch其实很简单...
  5. 计算机组成与人体类比,2020年安徽公务员考试真题模拟:类比推理(7.13)
  6. N个结点不同结构的二叉树个数
  7. 常用测试用例设计方法
  8. 谈谈Cost function and gradient的matlab写法
  9. lunix mysql创建视图_Linux命令:MySQL系列之六--VIEW视图/mysql -e
  10. 数据分析中会常犯哪些错误,如何解决? 三