模块化解决方案

156 阅读2分钟

模块化开发可以提高代码的复用率,便于管理。通常文件就是一个模块,有自己的作用域,只向外暴露特定的函数和变量。当下流行的JS模块化规范有:CommonJs、AMD、CMD、ES6 Module。

一、CommonJs

Node.js是Common.js规范的主要实践者,其四个重要的环境变量为模块化提供支持。module、exports、require、global。实际使用时,module.exports定义当前模块对外输出的接口(不推荐直接使用exports),用require加载模块。

// 自定义模块     commonModule.js  自定义变量 commonNumber 自定义函数  add
let commonNumber = 0;
function add(a, b) {
  return a + b;
}
// module.exports 对外暴露模块自定义变量、自定义函数
module.exports = {
    //在这里写上需要向外暴露的函数、变量
    add: add,
    commonNumber: commonNumber
}

// 引用自定义的模块时,参数包含路径,可省略.js
let math = require('./commonModule');
math.add(2, 5);

// 引用核心模块时,不需要带路径
let http = require('http');
http.createService(...).listen(3000);

CommonJs使用同步的方式加载模块,在服务端,模块文件都存储在本地磁盘,读取速度非常快。所以使用CommonJs规范没有问题。但在浏览器因收到网络因素限制,使用异步加载方式更为恰当。

二、AMD + RequireJs

AMD规范采用异步加载模式。其模块的加载不影响后续语句的执行。所有依赖这个模块的语句,都定义在一个回调函数内。等到依赖的这个模块加载完毕后,才会执行回调函数。

三、CMD + sea.js

CMD这种JS模块化方案与AMD很类似。AMD推崇依赖前置、提前执行。CMD推崇依赖就近、延迟执行。此规范是在sea.js推广过程中出现的。

四、ES6 Module

ES6在语言标准层面上,实现了模块化。而且实现的非常简单,旨在成为浏览器和服务器通用的模块化解决方案。其模块化功能主要由两个命令构成,export 和 import。export 用于规定模块对外的接口。import 为输入其它模块提供可能。

/** 定义模块 math.js **/ 
var basicNum = 0; 
var add = function (a, b) { return a + b; }; 
/** 抛出模块 方案一 **/ 
export { basicNum, add }; 
/** 抛出模块 方案二 **/ 
export default { basicNum, add }; 
/** 引用模块 方案一 **/ 
import { basicNum, add } from './math'; 
/** 引用模块 方案二 **/ 
import math from './math';

使用import命令的时候,用户需要知道所要加载的变量名或函数名。其实ES6还提供了export default命令,为模块指定默认输出,对应的import语句不需要使用大括号。这也更趋近于ADM的引用写法。

ES6模块不是对象,import命令会被javascript引擎静态分析,在编译时就引入了模块代码。而不是在代码运行时加载,所以无法实现条件加载。因为这个特性,使静态分析成为可能。