模块化及AMD、CMD、CommonJS、ES6的对比

模块化

概念: 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件)并进行组合。

模块的内部数据的实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信,这就是模块化。

优点: 模块化可以降低代码耦合度,减少重复代码,提高代码重用性,并且在项目结构上更加清晰,便于维护。

AMD、CMD、CommonJs、ES6的对比

他们都是用于在模块化定义中使用的,AMD、CMD、CommonJs是ES5中提供的模块化编程的方案,import/export是ES6中定义新增的

AMD

AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。AMD是一个组织,RequireJS是在这个组织下自定义的一套脚本语言

RequireJS:是一个AMD框架,可以异步加载JS文件,按照模块加载方法,通过define()函数定义第一个参数是一个数组,里面定义一些需要依赖的包,第二个参数是一个回调函数,通过变量来引用模块里面的方法,最后通过return来输出。

是一个依赖前置、异步定义的AMD框架(在参数里面引入js文件),在定义的同时如果需要用到别的模块,在最前面定义好即在参数数组里面进行引入,在回调里面加载

define(['./a', './b'], function(a, b) {
    a.do();
    b.do();
});
define(function(require,exports,module){
	var a = require('./a');
    a.doSomething();
    var b = require('./b');
    b.doSomething();
});

CMD

SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架.

通过define()定义,没有依赖前置,通过require加载jQuery插件,CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,这是一个同步的概念

define(id?, deps?, factory)

factory是一个函数,有三个参数,function(require, exports, module)

  1. require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口:require(id)
  2. exports 是一个对象,用来向外提供模块接口
  3. module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
// 定义模块  module.js
define(function(require, exports, module) {
  var $ = require('jquery.min.js')
  $('div').addClass('active');
});

// 加载模块
seajs.use(['module.js'], function(my){
});

AMD与CMD区别

AMD和CMD最明显的区别就是在模块定义时对依赖模块的执行时机处理不同。

1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块

js可以方便知道依赖模块是谁,立即加载;

2、CMD推崇就近依赖,只有在用到某个模块的时候再去require

需要使用把模块变为字符串解析一遍才知道依赖了那些模块,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略。

ES6

ES6模块的主要有两个功能:export和import。

  • export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口。
  • import用于在一个模块中加载另一个含有export接口的模块。

也就是说使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)。

//util1.js
export default {
    a: 100
}

//index.js
import util1 from './util1.js'
console.log(util1);
//util2.js
export function fn1() {
    alert('fn1');
}
export function fn2() {
    alert('fn2');
}

//index.js
import { fn1, fn2 } from './util2.js'
fn1();
fn2();

CommonJs

是通过module.exports定义的,在前端浏览器里面并不支持module.exports,通过node.js后端使用的。Nodejs端是使用CommonJS规范的,前端浏览器一般使用AMD、CMD、ES6等定义模块化开发的。

加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。

CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}

  • require()用来引入外部模块;
  • exports对象用于导出当前模块的方法或变量,唯一的导出口;
  • module对象就代表模块本身。
// a.js
module.exports = {
    a: 1;
}
// or
exports.a = 1;

// b.js
var module = require('./a.js');
module.a; // 1

commonjs和ES6模块化的区别

  • 前者支持动态导入,也就是require(${path}/xx.js),后者目前不支持,但是已有提案
  • 前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用导入会对渲染有很大影响
  • 前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。但是后者采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化。
  • 后者会编译成require/export来执行

你可能感兴趣的:(前端,JavaScript)