模块化的意思就是在解决某一问题时,采用分类的思想把问题进行系统性分解,从而解决问题的方式。目前JavaScript领域广泛使用的模块化规范包括,commonJs规范、AMD规范,CMD规范。
今天简单介绍下这三种开发规范。
一、commonjs规范
commonjs出现的背景和JavaScript的函数式编程有关,没有标准化模块化系统、标准库少等。所以commonjs就是为了解决这些问题而出现的。即提供很多普通应用程序(主要指非浏览器的应用)使用的API,提供包管理工具,模块化实现规范(定义)等等。
nodejs 就是基于此规范实现的,简单归纳commonjs其特性:
1、一个文件就是一个模块,拥有独立作用于。
2、提供require引入模块,提供export 导出模块属性方法,exports代表模块本身。
二、AMD规范
先解释下AMD名词的意思,全称是Asynchronous Module Definition,异步模块定义。AMD规范特性简单概括包括以下几点:
1、所有的模块都进行异步加载,模块加载不影响后面语句运行。
2、所有依赖某些模块的语句均放置在回调函数中。
3、提供全局define 函数(方法)来定义模块,require引入模块,exports导出模块。
使用AMD规范进行页面开发需要用到对应的库函数RequireJS。实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出。
requirejs 在实现JavaScript模块化开发的同时,主要是解决2个问题:
1、多个js模块相互引用问题,被依赖模块需早与依赖模块加载。
2、js加载的会阻塞浏览器页面渲染,加载文件越多,页面失去响应时间越长
AMD语法:定义了一个自由变量或者说是全局变量 define 的函数。
define( id?, dependencies?, factory )
1、id 为字符串类型,表示了模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。如果存在,那么模块标识必须为顶层的或者一个绝对的标识。
2、dependencies ,当前模块依赖的模块,已被模块定义的模块标识的数组字面量。
3、factory,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值
require([dependencies], function(){})
require()函数接受两个参数
1、第一个参数是一个数组,表示所依赖的模块
2、第二个参数是一个回调函数,当前面指定的模块都加载成功后,回调函数将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
三、CMD规范
CMD规范全称Common Module Definition通用模块定义,典型实现是seajs。seajs和requirejs 解决的问题一样,只是在只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同。
语法:
define(function(require,exports,module){...}) ,factory是一个函数,提供equire, exports, module三个参数:
1、require 是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口:require(id)
2、exports 是一个对象,用来向外提供模块接口
3、module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
四、AMD和CMD区别
AMD和CMD最大的区别是对依赖模块的执行时机处理不同:
1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
不同点体现如下:
1、异步加载模块
requireJS,SeaJS加载模块都是异步的,只不过AMD依赖前置,JS可以方便知道依赖模块是谁,立即加载。CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块。
2、依赖模块执行时机不同
AMD在加载模块完成后就会执行改模块,所有依赖模块都加载执行完后会进入require的回调函数执行主逻辑,依赖模块的执行顺序和书写顺序不一定一致,主逻辑一定在所有依赖加载完成后才执行。
CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。
参考:CommonJS规范
AMD (中文版)
js模块化编程之彻底弄懂CommonJS和AMD/CMD!
有错误之处,欢迎指正~~