上一篇文章中,我们聊到了”史前时代”js是如何”模拟”模块化的,但本质上依旧是用“旁门左道”来实现的,并不是js语言层面的规范,要想真正实现模块化,肯定需要js自己本身去推出模块化相关的规范,因此这篇文章就准备聊聊这些规范,废话不多说,开搞!

bqb

Commonjs

Nodejs 使用的就是Commonjs规范,主要通过提供module,exports,require来实现模块化,require方能看到的只有module.exports这个对象,它是看不到exports对象的,而我们在编写模块时用到的exports对象实际上只是对module.exports的引用,通常情况下更建议使用 module.exports 而不是 exports,该规范的用法如下:

1
2
3
4
5
6
7
8
9
10
//a.js
var name = 'test'

module.exports = {
name
}

//b.js
var moduleA = require('./a.js')
console.log(moduleA.name)

这种规范具有如下几个特点

AMD

AMD规范的主要践行者是 Requirejs,它主要通过 define,require来实现模块化,具体用法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/** 网页中引入require.js及main.js **/
<script src="js/require.js" data-main="js/main"></script>

/** main.js 入口文件/主模块 **/
// 首先用config()指定各模块路径和引用名
require.config({
baseUrl: "js/lib",
paths: {
"jquery": "jquery.min", //实际路径为js/lib/jquery.min.js
"test1": "test1",
"test2": "test2"
}
});

// 定义test1.js模块
define(function () {
return {
name: 'test1'
};
});
// 定义一个依赖test1.js的test2模块
define(['test1'],function(test1){
return {
name: test1.name + 'test2'
};
})

// 引用模块
require(["jquery","test1","test2"],function($,test1,test2){
// some code here
});

该模块规范的特点如下:

CMD

CMD吸取了AMD和cjs的优点,因此是一种相对前两者更好的模块化方案,Seajs 是该规范的主要践行者,具体用法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//定义没有依赖的模块
define(function(require, exports, module){
exports.xxx = value
module.exports = value
})

//定义有依赖的模块
define(function(require, exports, module){
//引入依赖模块(同步)
var module2 = require('./module2')
//引入依赖模块(异步)
require.async('./module3', function (m3) {
})
if(false) {
var moduleFalse = require('./moduleFalse') //该模块不会被导入
}
//暴露模块
exports.xxx = value
})





// main.js文件
define(function (require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
//在index.html中引入
<script type="text/javascript" src="js/libs/sea.js"></script>
<script type="text/javascript">
seajs.use('./js/modules/main')
</script>

该模块规范有如下特点:

ES module

ES module是 ES6 中提出来的模块化方案,旨在统一浏览器和服务器的模块化规范,也是直接从语言层面来规范js的模块化,所以未来ES module肯定是最终发展的方向,它的具体用法如下

1
2
3
4
5
6
7
8
9
10
/*a.js*/
export let a = 1
export default {
name:'yy'
}


/*b.js*/
import {a},aModule from './a.js'
console.log(a,aModule.name)

该规范有如下特点

结语

未来是 ES module 的天下,只不过现在还处在一个过渡的时期,因此有必要去了解除ES module外的规范,这样我们才能对js这门语言有更加深刻的认识,从而成为一个专业的前端工程师,所以,加油吧,骚年!