什么是模块?模块是把一个复杂程序按照一定规范封装成几个块(文件),组装在一起;内部数据私有,对外只暴露接口。
模块化的好处?防止命名空间污染;按需加载;提高复用性和可维护性。
页面中有多个script标签,一是会导致请求过多;二是不知道各个文件之间的依赖关系,可能导致加载先后顺序错乱。所以需要模块化规范来解决这两个问题。
CommonJS
CommonJS规范主要用于服务端(nodejs)编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。在浏览器上运行需借助browserify.(require)
AMD
AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。(require.js这个库就使用了AMD规范)
CMD
CMD规范与AMD规范很相似,都用于浏览器编程,模块加载也是异步的,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重(Sea.js这个库就使用了CMD规范)
ES6 Module
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范(ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。),成为浏览器和服务器通用的模块解决方案。(import)
ES6 模块与 CommonJS 模块的差异:
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。(ES6 模块的运行机制与 CommonJS 不一样。ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。(因为CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。)