模块化

模块化开发在现代开发中已是必不可少的一部分,它大大提高了项目的可维护、可拓展和可协作性。通常,我们 在浏览器中使用 ES6 的模块化支持,在 Node 中使用 commonjs 的模块化支持。

在有 Babel 的情况下,我们可以直接使用 ES6 的模块化

1
2
3
4
5
6
7
8
// file a.js
export function a() {}
export function b() {}
// file b.js
export default function () {}

import { a, b } from "./a.js";
import XXX from "./b.js";

CommonJs 是 Node 独有的规范,浏览器中使用就需要用到 Browserify 解析了。

1
2
3
4
5
6
7
8
9
10
// a.js
module.exports = {
a: 1,
};
// or
exports.a = 1;

// b.js
var module = require("./a.js");
module.a; // -> log 1

在上述代码中,module.exports 和 exports 很容易混淆,让我们来看看大致内部实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var module = require("./a.js");
module.a;
// 这里其实就是包装了一层立即执行函数,这样就不会污染全局变量了,
// 重要的是 module 这里,module 是 Node 独有的一个变量
module.exports = {
a: 1,
};
// 基本实现
var module = {
exports: {}, // exports 就是个空对象
};
// 这个是为什么 exports 和 module.exports 用法相似的原因
var exports = module.exports;
var load = function (module) {
// 导出的东西
var a = 1;
module.exports = a;
return module.exports;
};

再来说说 module.exports 和 exports,用法其实是相似的,但是不能对 exports 直接赋值,不会有任何效果。

对于 CommonJS 和 ES6 中的模块化的两者区别是:

require 支持 动态导入,import 不支持,正在提案 (babel 下可支持)
require 是 同步 导入,import 属于 异步 导入
require 是 值拷贝,导出值变化不会影响导入值;import 指向 内存地址,导入值会随导出值而变化