模块的定义:
可以理解成实现特定功能的相互独立的一组方法
为什么要使用模块化:
- 可维护性
- 命名空间
- 可复用性
模块化规范
- CommonJS
- Module(es6)
- AMD
- UMD
- CMD
common.js 和 es6 中模块引入的区别?
CommonJS 是一种模块规范,最初被应用于 Nodejs,成为 Nodejs 的模块规范。
运行在浏览器端的 JavaScript 由于也缺少类似的规范,在 ES6 出来之前,前端也实现了一套相同的模块规范 (例如: AMD),用来对前端模块进行管理。
自 ES6 起,引入了一套新的 ES6 Module 规范,在语言标准的层面上实现了模块功能,而且实现得相当简单,有望成为浏览器和服务器通用的模块解决方案。
但目前浏览器对 ES6 Module 兼容还不太好,我们平时在 Webpack 中使用的 export 和 import,会经过 Babel 转换为 CommonJS 规范。
在使用上的差别主要有:
1、CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
2、CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
3、CommonJs 是单个值导出,ES6 Module可以导出多个
4、CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
5、CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
CommonJS
CommonJS 是一套 Javascript 模块规范,用于服务端
CommonJS 扩展了JavaScript声明模块的API,
通过CommonJS,每个JS文件独立地存储它模块的内容(就像一个被括起来的闭包一样)。在这种作用域中,我们通过 module.exports 语句来导出对象为模块,再通过 require 语句来引入
- 所有代码都运行在模块作用域,不会污染全局作用域
- 模块是同步加载的,即只有加载完成,才能执行后面的操作
- 模块在首次执行后就会缓存,再次加载只返回缓存结果,如果想要再次执行,可清除缓存
- require返回的值是被输出的值的拷贝,模块内部的变化也不会影响这个值
如:
function myModule() {
this.hello = function() {
return 'hello!';
}
}
module.exports = myModule;
// 然后再通过require去加载
ES Module
原生JS(es6)解决方案, ES6设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量
模块功能主要由两个命令构成:
export:用于规定模块的对外接口
import:用于输入其他模块提供的功能
如:
export default myModule
import myModule from './myModule'
动态加载
允许您仅在需要时动态加载模块,而不必预先加载所有模块,这存在明显的性能优势
这个新功能允许您将import()作为函数调用,将其作为参数传递给模块的路径。它返回一个 promise,它用一个模块对象来实现,让你可以访问该对象的导出
import('/modules/myModule.mjs')
.then((module) => {
// Do something with the module.
});
复合写法
如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起
export { foo, bar } from 'my_module';
// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };
同理能够搭配as、*搭配使用
AMD (Asynchronous Module Definition)
提倡依赖前置,在定义模块的时候就要声明其依赖的模块
异步模块定义,采用异步方式加载模块。所有依赖模块的语句,都定义在一个回调函数中,等到模块加载完成之后,这个回调函数才会运行
代表库为require.js
如:
/** main.js 入口文件/主模块 **/
// 首先用config()指定各模块路径和引用名
require.config({
baseUrl: "js/lib",
paths: {
"jquery": "jquery.min", //实际路径为js/lib/jquery.min.js
"underscore": "underscore.min",
}
});
// 执行基本操作
require(["jquery","underscore"],function($,_){
// some code here
});
CMD (Common Module Definition)
CMD规范是国内SeaJS的推广过程中产生的
提倡就近依赖(按需加载),在用到某个模块的时候再去require
define(function (require, exports, module) {
var one = require('./one')
one.do()
// 就近依赖,按需加载
var two = require('./two')
two.do()
})
UMD (Universal Module Definition)
AMD和CommonJS的结合,跨平台的解决方案,UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块
如
(function (window, factory) {
if (typeof exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
window.eventUtil = factory();
}
})(this, function () {
//module ...
});