模块化CommonJS与AMD的手写实现

  目录

javascript模块化CommonJS与AMD是如何实现的

模块化CommonJS与AMD的手写实现

现在的前端开发都采用的模块化思想,之前都是使用全局变量,但是弊端这里就不过多描述了。
模块化有CommonJS,AMD,CMD,ES6的模块新规范这4种,今天我们来实现以下CommonJS和AMD的规范。

CommonJS

首先,CommonJS一般都用在nodejs里,写法如下:

1
2
3
4
5
// 导入
const someFun= require('./moduleA');
someFun();
// 导出
module.exports = someFunc;

我们来看一下简单的实现方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// a.js
let fs = require('fs');
let path = require('path');
let b = req('./b.js');
function req(mod) {
let filename = path.join(__dirname, mod);
let content = fs.readFileSync(filename, 'utf8');
let fn = new Function('exports', 'require', 'module', '__filename', '__dirname', content + '\n return module.exports;');
let module = {
exports: {}
};

return fn(module.exports, req, module, __filename, __dirname);
}

// b.js
console.log('bbb');
exports.name = 'zfpx';

AMD

我们再来看看AMD规范,AMD规范的实现库是大名鼎鼎requirejs

1
2
3
4
5
6
7
8
9
10
11
// 定义一个模块
define('a', [], function () {
return 'a';
});
define('b', ['a'], function (a) {
return a + 'b';
});
// 导入和使用
require(['b'], function (b) {
console.log(b);
});

简单的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let factories = {};
function define(modName, dependencies, factory) {
factory.dependencies = dependencies;
factories[modName] = factory;
}
function require(modNames, callback) {
let loadedModNames = modNames.map(function (modName) {
let factory = factories[modName];
let dependencies = factory.dependencies;
let exports;
require(dependencies, function (...dependencyMods) {
exports = factory.apply(null, dependencyMods);
});
return exports;
})
callback.apply(null, loadedModNames);
}

ES6 模块化

ES6 模块化是ECMA提出的JavaScript模块化规范,它在语言的层面上实现了模块化。浏览器厂商和Node.js 都宣布要原生支持该规范。它将逐渐取代CommonJS和AMD`规范,成为浏览器和服务器通用的模块解决方案。 采用 ES6 模块化导入及导出时的代码如下

1
2
3
4
// 导入
import { name } from './person.js';
// 导出
export const name = 'zfpx';

ES6模块虽然是终极模块化方案,但它的缺点在于目前无法直接运行在大部分 JavaScript 运行环境下,必须通过工具转换成标准的 ES5 后才能正常运行。