JS模块化

295 阅读3分钟

什么是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()方法来执行这个模块。