目前流行的js模块化规范有commonJS, AMD, CMD, 以及ES6的模块系统

一、commonJS
js没有完善的模块系统,标准库较少,缺少包管理工具,伴随着Nodejs的兴起,能让js在任何地方运行。特别是服务端,也达到了具备开发大型项目的能力,所以commonjs营运而生。

node.js是commonjs规范的主要实践者。它有四个重要的环境变量为模块化的实现提供支持:
moudle, exports, require, global.
实际使用中,用module.exports定义当前模块对外输出的接口(不推荐直接用exports),用require加载模块。

commonjs用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题,但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。

暴露模块:

moudle.exports = value
  exports.xxx = value

commonjs规范:

一个文件就是一个模块,拥有单独的作用域;普通方式定义的变量、函数,对象都属于该模块内;通过require来加载模块;通过exports 和module.exports来暴露块中的内容。

注意点:

  1. exports和module.exports同时存在时,module.exports会覆盖exports.
  2. 当模块内全是exports时,就等于moudle.exports
  3. exports就是module.exports的子集
  4. 所有的代码都运行在模块作用域,不会污染全局作用域
  5. 模块可多次加载,但只会在第一次加载时候运行,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。
  6. 模块加载顺序,按照代码出现的顺序同步加载。
  7. __dirname代码当前文件所有的文件夹路径
  8. __filename代表当前模块文件所有的文件夹路径+文件名

二、es6模块化

es6在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:export和import.export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

其实es6还提供了export default命令,为模块指定默认输出 ,对应的import语句不需要使用大括号,这也更趋近于AMD的引用写法。

es6模块不是对象,import命令会被js引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正是因为这个,使得静态分析成为可能。

export可以导出一个对象中包含的多个属性,方法。export default只能导出一个可以不具名的函数。我们可以通过import进行引用。同时,我们也可以直接使用Require使用,原因是webpack起了server相关。

import {fn} from './xxx/xxx' //这个是export导出方式 
import fn from './xxx/xxx' //这个是exportdefault导出方式