首页技术文章正文

JavaScript 模块化

更新时间:2018-07-27 来源:黑马程序员 浏览量:

模块化发展历程
js一开始并没有模块化的概念,直到ajax被提出,前端能够像后端请求数据,前端逻辑越来越复杂,就出现了许多问题:全局变量,函数名冲突,依赖关系不好处理。 
当时使用子执行函数来解决这些问题,比如经典的jquery就使用了匿名自执行函数封装代码,将他们全都挂载到全局变量jquery下边。

CommonJs
CommonJs通过nodeJs发扬光大,每个js文件就是一个模块,每个模块有单独的作用域。模块以module.exports为出口,输出一个对象。使用require方法读取文件,并返回其内部的module.exports对象。

CommonJs的问题在于,他的加载是同步的,这在服务端很正常,但是在充满了异步的浏览器里,就不适用了。为了适应浏览器,社区内部发生了分歧。

AMD
AMD 即Asynchronous Module Definition,中文名是异步模块定义的意思。它是一个在浏览器端模块化开发的规范,由于不是JavaScript原生支持,AMD的作者亲自实现了符合AMD规范的RequireJS。 
AMD规范规定用全局函数define来定义模块,用法为define(id, dependencies, factory);其中,id为模块标识,dependencies是一个数组,数组里边是该模块依赖的其他模块,factory则是一个匿名函数,里边是该模块的逻辑。 
目前公司使用的就是AMD规范。 
例如:

//main.js
require(['a', 'b'], function(a, b){
     console.log('main.js执行');
     a.hello();
     $('#b').click(function(){
          b.hello();
     });
})
requireJs的问题在于,加在一个模块时,会预先加载该模块的所有依赖模块,但是这些依赖很可能一开始并不用到。同时依赖写起来一长串,也很麻烦。比较好的是AMD保留了commonJs中的require、exprots、module3个功能,可以不把以来都写在dependencies中,而是在需要时使用require引入。

CMD
既然requirejs有上述种种不甚优雅的地方,所以必然会有新东西来完善它,这就是后起之秀seajs,seajs的作者是国内大牛淘宝前端步道者玉伯。seajs全面拥抱Modules/Wrappings规范,不用requirejs那样回调的方式来编写模块。而它也不是完全按照Modules/Wrappings规范,seajs并没有使用declare来定义模块,而是使用和requirejs一样的define,或许作者本人更喜欢这个名字吧。(然而这或多或少又会给人们造成理解上的混淆),用seajs定义模块的写法如下:

//main.js
define(function(require, exports, module){
     console.log('main.js执行');
     var a = require('a');
     a.hello();    
     $('#b').click(function(){
          var b = require('b');
          b.hello();
     });

});

定义模块时无需罗列依赖数组,在factory函数中需传入形参require,exports,module,然后它会调用factory函数的toString方法,对函数的内容进行正则匹配,通过匹配到的require语句来分析依赖,这样就真正实现了commonjs风格的代码。

AMD与CMD的区别
AMD和CMD最明显的区别就是在模块定义时对依赖的处理不同 
AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块 
CMD推崇就近依赖,只有在用到某个模块的时候再去require 
这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法

面向未来的ES6模块标准
ES6考虑了模块化,使用import和export,但是目前浏览器还不支持,这个标准也只是个雏形。


作者:黑马程序员前端与移动开发培训学院
首发:http://web.itheima.com/



分享到:
在线咨询 我要报名
和我们在线交谈!