JavaScript模块化
为什么要使用模块化
所谓的模块化,就是将网页的功能打包成单独的模块来使用,一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。
使用模块化的主要目的
- 解决命名冲突
- 依赖管理
使用模块化的次要目的 - 提高可读性
- 代码解耦,提高复用性
CMD,AMD,commonJS
CMD
所谓的CMD是common module definition的缩写,CMD规范是国内发展出来的,就类似AMD有个requireJS,CMD有SeaJS一样,requireJS和SeaJS所要解决的问题一样,只是在解决问题的手段上存在着一些差异
语法
SeaJS遵从一个模块一个文件的写法,因此就常用文件名作为模块ID。
CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写。
factory有三个参数
factory(require, exports, module)
require
require是factory中的第一个参数
require(id)
require是一个方法,接受 模块标识 为唯一参数,用来获取其他模块的提供的接口。
exports
exports是一个对象,用来对外界提供模块接口
module
module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
demo
// 定义模块 myModule.js
define(function(require, exports, module) {
var $ = require('jquery.js')
$('div').addClass('active');
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});
AMD
AMD指的是Asynchronous Module Definition,由于不是原生JS支持,使用AMD所对应的函数库也就是requireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出。
AMD主要解决两个问题
- 多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
- js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长
语法
require定义了一个函数define,它是全局变量,用来定义模块
define(id?, dependencies?, factory);
- id:可选参数,用来定义模块的标识,如果没有提供该参数,脚本文件名(去掉拓展名)
- dependencies:是一个当前模块依赖的模块名称数组
- factory:工厂方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值
在页面上使用require函数加载模块
require([dependencies], function(){})
require()函数接受两个参数,分别为
- 第一个参数是一个数组,表示所依赖的模块
- 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
commonJS
CommonJS是服务器端模块的规范,Node.js采用了这个规范。Node.JS首先采用了js模块化的概念。
-
在一个模块中,存在自由变量require,它是一个函数
1.这个”require”函数接收一个模块标识符。
2.“require”返回外部模块所输出的API。
3.如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所require的时候可能并没有执行完成;在这种情况下,”require”返回的对象必须至少包含此外部模块在调用require函数(会进入当前模块执行环境)之前就已经准备完毕的输出。
4.如果请求的模块不能返回,那么”require”必须抛出一个错误。 -
在一个模块中,会存在一个名为”exports”的自由变量,它是一个对象,模块可以在执行的时候把自身的API加入到其中。
-
模块必须使用”exports”对象来做为输出的唯一表示。