什么是js模块化?
js模块化就是一个个拥有特定功能的文件,他们有特定的规范,有特定的约束,通过固定的方式引入,并且通过固定的方式向外暴露指定的内容。有了模块化我们可以更方便的使用别人的代码,可以大大加快开发效率。
为什么要使用模块化
因为前段技术逐渐成熟,我们可以用js干很多很多事情,这导致了我们的js代码量越来越庞大,团队需要分工合作,进度管理、单元测试等等.....使用模块化来管理业务逻辑已经成为一个迫切的需求。
今天要讲的几个模块化规范CMJ、AMD、CMD、ESM
CMJ(CommonJS规范)
谈到CMJ我们很容易想到node.js因为node所使用的模块化规范正是CMJ,侧面说明了CMJ是一个适用与服务器的模块化规范。
CMJ有几个主要方法分别为:module、exports、require、global。
在开发中我们用module.exports 来导出模块,用 require来加载模块。
我们来看个简单的用例:
math.js
//在math.js中,我们定义了一个变量和一个函数并把它暴露出来
let num = 0;
function add(a, b) {
return a + b;
}
module.exports = { //在这向外暴露出函数与变量
add: add,
num: num
}
index.js
//我们在这里使用require方法引用math.js
let math = require('./math');
//这时我们可以调用到math中的add方法。
math.add(4, 9);
这里要注意的是引用自定义的模块时,参数包含路径,可省略.js,而引用核心模块时,不需要带路径。
因为CommonJS用同步的方式加载模块。在浏览器中我们用同步方式加载模块时用户将无法继续操作网页,所以前端需要一个能异步加载模块的模块化规范。
AMD
AMD就是一个异步加载模块的模块化规范。AMD的实现就是require.js
AMD规范定义了一个函数define,通过define方法定义模块
define(id?, dependencies?, factory);
id:可选参数,用来定义模块的标识,如果没有提供该参数,模块标识就取脚本文件名(去掉扩展名)。
dependencies:可选参数,用来传入当前模块依赖的模块名称数组。
factory:工厂方法,模块初始化要执行的函数或对象,如果是函数,它只被执行一次。如果是对象,此对象应该为模块的输出值。定义模块例子:
define('a', function () {
console.log('a load')
return {
run: function () { console.log('a run') }
}
})
在require.js 中还有require.config和require,我们以加载一个jquery库为例:
require.config({
paths : {
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"]
}
})
//这时做完上面的操作后我们就可以直接用jquery来引入模块,不用后面那一大串CDN地址了
require(["jquery"],function($){
$(function(){
alert("load finished");
})
})
依赖前置:
define('a', function () {
console.log('a load')
return {
run: function () { console.log('a run') }
}
})
define('b', function () {
console.log('b load')
return {
run: function () { console.log('b run') }
}
})
require(['a', 'b'], function (a, b) {
console.log('main run')
a.run()
b.run()
})
// a load
// b load
// main run
// a run
// b run
//从这个打印结果我们可以看出,ADM在require时就把所有模块都加载了并没有管你有没有用到他,这就是依赖前置。
CMD
代表技术实现 Seajs
CMD例子:
//function有三个参数:require参数用来引入别的模块,exports和module用来导出模块公共接口。
define('a', function (require, exports, module) {
console.log('a load')
exports.run = function () { console.log('a run') }
})
define('b', function (require, exports, module) {
console.log('b load')
exports.run = function () { console.log('b run') }
})
define('main', function (require, exports, module) {
console.log('main run')
var a = require('a')
a.run()
var b = require('b')
b.run()
})
seajs.use('main')
我们可以看到我们的依赖是用require按需要来引入的。这就是依赖后置。而且我们需要调用seajs.use()方法来执行这个模块。