有人说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

AMD and CMD are dead之KMDjs内核之依赖分析的更多相关文章

  1. AMD and CMD are dead之KMDjs内核之分号

    在老版本的kmdjs中,强制了分号的要求.但是总感觉不爽,因为在开发Ket - Kmdjs Extension Tools的时候,总需要导入一些开源的库,然后痛苦就来了,总是报错,一查,就是缺少分号! ...

  2. AMD and CMD are dead之KMDjs集成Blob一键下载全部build包

    更新 不zuo,[A/C]MD就不会死,所以kmdjs赢来来其伟大的版本0.0.6,该版本主要的更新有: 移除去了kmdjs.get(..).then的支持,只支持kmdjs.get(-,functi ...

  3. AMD and CMD are dead之KMDjs在JS工程化的努力

    总览 kmdjs发布了最接近最终版本的0.0.4版本https://github.com/kmdjs/kmdjs,你已经完全可以在项目中使用.我已经无法用语言形容其完美程度.借用我发的微博:   模块 ...

  4. AMD and CMD are dead之KMD规范

    What's KMD? 乱世出英雄,KMD名字的由来充满了杀气. Kill AMD and CMD KMD为替代混乱的AMD和CMD世界而生,一统天下.或者让这个混乱的世界更加混乱,导致: KMD A ...

  5. AMD and CMD are dead之KMD.js之懒

    缘由 "懒"在软件设计中,有着重大的意义.最常见的两种"懒",便是: 懒得计算 懒得加载 "懒得计算"常见于服务器端: 比如Multipla ...

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

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

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

    var define, require, define2, require2; typeof JSON != "object" && (JSON = {}), fu ...

  8. AMD and CMD are dead之Why Namespace?

    缘由 当我看到_Franky兄的微博的时候: 我觉得我有必要出来详细说说KMDjs到底有什么本质上的优势了,连教主_Franky.貘吃馍香都不能理解他的好处,那么可想而知,在前端圈.或是全端圈.或是I ...

  9. AMD and CMD are dead之JS工程化终极解决方案KMD.js版本0.0.1发布

    回顾 经过两天晚上疯狂的开发调试,伴随着大量掉落的头发和酸痛的颈椎,KMD.js赢来了第一个稳定版本.在此期间KMD规范也有所修改和完善. 这两天主要完成的功能有: 按需加载 版本控制 模块管理 便捷 ...

随机推荐

  1. IOS系列swift语言之课时二

    今天我们要讲的就是函数[对于函数,在最后面还有几道题,喜欢的博友可以看了自己做一下,和我交流一下] 当然这与我们的c语言还是有一定的共同之处的,对于有一些c语言或者是java基础的童鞋,我觉得是很容易 ...

  2. Nginx配置文件nginx.conf详解

    #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 8; #全局错误日志定义类型,[ debug | ...

  3. LINQ系列:Linq to Object相等操作符

    相等操作符通过比较两个序列来检查它们相应的元素是否相同.如果两个序列有相同的元素,并且对应元素的值相同,则认为这两个序列是相等的. SequenceEqual操作符判定两个集合是否相等.判定是通过并行 ...

  4. Easyui 让DataGrid适应浏览器宽度

    DataGrid有100%宽度的设置,但是有时不是很让人满意,比如你你放大或者拉放你的浏览器,那么DataGrid只维持第一次加载的宽高,非常难看 $('#List').datagrid({ url: ...

  5. 应用程序框架实战十八:DDD分层架构之聚合

    前面已经介绍了DDD分层架构的实体和值对象,本文将介绍聚合以及与其高度相关的并发主题. 我在之前已经说过,初学者第一步需要将业务逻辑尽量放到实体或值对象中,给实体“充血”,这样可以让业务逻辑高度内聚, ...

  6. 如何部署Icinga客户端

    Icinga客户端的部署相对于服务器端来说,简单很多.对于服务器端来说,如果要通过以下这种方式来监控服务器,必须包含三个组件,Icinga内核,Icinga插件,NRPE(Nagios Remote ...

  7. [OpenCV] Background subtraction

    不错的草稿.但进一步处理是必然的,也是难点所在. http://docs.opencv.org/master/d1/dc5/tutorial_background_subtraction.html#g ...

  8. Oracle监控用户索引使用情况,删除无用索引

    监控当前业务用户索引 一段时间后查询从未被使用的索引,删除无用索引 停止监控索引 1. 监控当前用户所有索引 得到监控所有索引的语句: select 'alter index ' || index_n ...

  9. 初识Spring

    Spring简介 说到Spring就得提到它的作者"Rod Johnson",2002年他编写了<Expert One-on_One java EE设计与开发>一书.在 ...

  10. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...