在 es6 之前,没有能提出一套官方的规范,而从社区和框架推广程度而言,通行的 javascript 模块规范有两种:CommonJS 和 AMD,但是现在 es6 的 module 已经实现了,所以目前我们只需要了解CommonJS 和 ES6 modules 规范即可。
CommonJS规范

2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。
这标志”Javascript模块化编程”正式诞生。前端的复杂程度有限,没有模块也是可以的,但是在服务器端,一定要有模块与操作系统和其他应用程序互动,否则根本没法编程。
node 编程中最重要的思想之一就是模块化,而正是这个思想,让 JavaScript 的大规模工程成为可能。模块化编程在 js 界流行,也是基于此,随后在浏览器端,require.js 和 sea.js 之类的工具包也出现了,可以说在对应规范下,require 统治了 ES6 之前的所有模块化编程,即使现在,在 ES6 module 被完全实现之前,还是这样。
在 CommonJS 中,暴露模块使用 module.exports
和 exports
,很多人不明白暴露对象为什么会有两个,看下面的例子介绍区别
module.exports = value //value可以是任意类型的值
exports.xxx = value //你也可以通过export的属性向外暴露
无论是哪种方式,本质上向外暴露的都是exports对象,在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。
let math = require('math') //如果是自定义模块,可以使用相对路径读取
然后,就可以调用模块提供的方法:
let math = require('math')
math.add(2,3) // 5
也正是由于 CommonJS 使用的require方式的推动,才有了后面的AMD、CMD 也采用的require方式来引用模块的风格。
ES6的模块化标准

ES6 标准发布后,module 成为标准,模块化标准的使用是以 export 指令导出接口,以 import 引入模块。(但是在我们一贯的 node 模块中,我们依然采用的是 CommonJS 规范,使用 require 引入模块,使用 module.exports 导出接口。)
ES6 中 export 和 import 一般的用法有两种
- 命名导出(Named exports)
- 默认导出(Default exports)
命名导出(Named exports)
就是每一个需要导出的数据类型都要有一个 name,统一引入一定要带有 {},即便只有一个需要导出的数据类型。这种写法清爽直观,是推荐的写法。
//------ lib.js ------
const sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function diag(x, y) {
return sqrt(square(x) + square(y));
}
export {sqrt, square, diag}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
或者把 export 直接加到声明前面
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
无论怎样导出,引入的时候都需要解构 {}。
默认导出(Default exports)
默认导出就不需要 name 了,但是一个js文件中只能有一个 export default。
//------ myFunc.js ------
export default function () { ... };
//------ main1.js ------
import myFunc from 'myFunc';
myFunc();
其实这种导出方式可以看成是命名到处的变种,只不过把命名写成了default。
虽然 export default 只能有一个,但也可以导出多个方法。
export default {
speak () {
return 'moo'
},
eat () {
return 'cow eats'
},
drink () {
return 'cow drinks'
}
}
引入与命名空间引入类似
import cow from './default-cow.js'
import goat from './default-goat.js'
cow.speak() // moo
goat.speak() // baa
网友评论