为什么要模块化?模块化使代码结构更清晰维护起来更方便。
为什么要模块化规范?有了模块,我们可以方便地使用别人的代码。但大家都需要以同样的规范编写模块,所以有了模块规范。
JS中的模块规范:CommonJS(node.js), AMD(require.js), CMD(sea.js)。
CommonJS:
JS官方定义的API只能构建基于浏览器的应用程序。CommonJS 定义了很多普通应用程序(主要指非浏览器的应用)使用的API,从而填补了这一块空白。它的终极目标是提供一个类似于Python, Ruby和Java标准库,这样开发者可以使用CommonJS编写应用程序,这些应用可以运行在不同的javascript解释器和不同的主机环境中。
2009年,node.js诞生了,将javascript应用于服务端编程,标志着“javascript模块化编程”正式诞生(服务器端编程特别复杂,一定要有模块化)。Node.js的模块系统是参照CommonJS规范实现的,webpack也是以CommonJS的形式来写的。另外NPM是Node的包管理器,是为了帮助Node解决依赖包安装的问题,也遵循CommonJS规范。
CommonJS定义的模块分为:模块引用(require)、模块定义(exports)、模块标识(module)。浏览器不兼容CommonJS的根本原因是缺少4个Node.js环境的变量module、exports、require、global,这还不是CommonJS不适用于客户端的主要原因,缺少的变量函数我们可以自己封装出来。主要原因是模块加载在服务器端是同步加载,而在客户端是异步加载,需要等待时间。
AMD:
基于CommonJS规范的nodeJS出来后,服务端模块概念形成,客户端也想要模块化,且最好两者能够兼容,即一个模块在服务端和客户端都可以运行。但CommonJS有一个局限性导致其不适用于浏览器环境,例如 :var math = require('math'); math.add(2, 3) 执行math.add必须得等math.js加载完成才运行,如果加载时间很长,整个应用会停在这里,是同步加载。这在服务器端不是问题,因为所有模块都放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是在浏览器端,模块需要异步加载,等待时间取决于网速,这就是AMD规范诞生的背景。
它采用异步加载模块,模块加载不影响它后面代码的运行。AMD也采用require()语句加载模块,但是不同于CommonJS,它多了一个回调函数作为参数,require([module], callback)
CMD:
CMD的AMD很相似,但模块的运行机制不大一样。CMD对模块的态度是懒执行,只会在真正需要使用(依赖)模块时才执行该模块,行模块的顺序也是严格按照模块在代码中出现(require)的顺序。 而AMD对模块的态度是预执行,先尽早地执行(依赖)模块, 相当于所有的require都被提前了。