JavaScript 语言最初设计的主要作用仅仅是用来验证表单输入的有效性,为Web页面添加一些动画效果等,并不包含太多的高级语言的特性,此时通常直接在HTML页面中编写简单的 JS 代码或从外部引入一个 JS 文件即可。
随着前端开发技术的发展和演化,JS 在应用程序中的地位显著提升(甚至已经扩展到了服务端应用,如:Node.js),伴随而来的是前端 JS 代码的复杂度也在相应的不断提高,因此 JS 模块化编程成为了一个迫切需要解决的问题。
JS 模块化是将一个大的 JS 文件根据功能或职责的需要,拆分成多个相互独立或依赖的小 JS 文件,再进行统一的拼装或加载。
JS 文件拆分后进一步细化了每个文件的具体职责:
在早期的开发过程中就是将重复的代码封装到函数中,再将一系列的函数放到一个文件中(HTML或JS)
这种情况下全局函数的方式只能认为它们属于一个模块,但是程序并不能区分哪些函数是同一个模块,如果仅仅从代码的角度来说,这时没有任何模块的概念。
通过添加命名空间的形式从某种程度上解决了变量命名冲突的问题,但是并不能从根本上解决命名冲突。
此时从代码级别可以明显区分出哪些函数属于同一个模块。
利用此方式将函数包装成一个独立的作用域,私有空间的变量和函数不会影响到全局作用域(私有公有成员分离)。
以返回值的方式得到模块的公共成员,公开公有方法,可以隐藏私有空间内部的属性。此方式可以有选择的对外暴露自身成员。从某种意义上来说,解决了变量命名冲突的问题。
注:浏览器目前还不完全支持 ES6 模块,利用 Babel(https://babeljs.io/) 库可以将其转换为 ES5 的写法。
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
require.js ( RequireJS )实现AMD规范的模块化JS库
CMD是另一种国内发展出来的js模块化方案,它与AMD很类似,不同点在于:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。
sea.js ( https://github.com/seajs/seajs )实现CMD规范的模块化JS库
Node.js是commonJS规范的主要实践者,CommonJS 的模块提案为在服务器端声明模块指定了一个简单的 API。
CommonJS 已经过时,Node.js 的内核开发者已经逐渐废弃了该规范。
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。
ES6 模块功能主要由两个命令构成:export 和 import。
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能