Skip to content

模块

发展历程

我们梳理一下模块化的发展情况:

无模块化-->CommonJS 规范-->AMD 规范-->CMD 规范-->ES6 模块化

  • CommonJS 规范 Node 中模块化规范

Commonjs 的诞生给 js 模块化发展有了重要的启发,Commonjs 非常受欢迎, 但是局限性很明显:Commonjs 基于 Node 原生 api 在服务端可以实现模块同步加载, 但是仅仅局限于服务端,客户端如果同步加载依赖的话时间消耗非常大,所以需要一个 在客户端上基于 Commonjs 但是对于加载模块做改进的方案,于是 AMD 规范诞生了。

  • AMD 规范, 异步模块定义, 允许指定回调函数,AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到所有依赖加载完成之后(前置依赖),这个回调函数才会运行。

  • CMD 规范,同样是受到 Commonjs 的启发,国内(阿里)诞生了一个 CMD(Common Module Definition)规范。该规范借鉴了 Commonjs 的规范与 AMD 规范,在两者基础上做了改进。

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

AMD 推崇依赖前置、提前执行 CMD 推崇依赖就近、延迟执行。

  • 到了 2015 年,ES6 规范中,终于将模块化纳入 JavaScript 标准,从此 js 模块化被官方扶正,也是未来 js 的标准. 在 ES6 中,我们可以使用 import 关键字引入模块,通过 exprot 关键字导出模块,功能较之于前几个方案更为强大,也是我们所推崇的, 但是由于 ES6 目前无法在浏览器中执行,所以,我们只能通过 babel 将不被支持的 import 编译为当前受到广泛支持的 require。

export

模块功能主要由两个命令构成:export 和 import。export 命令用于规定模块的对外接口,import 命令用于输入其他模块提供的功能。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用 export 关键字输出该变量。

  • 导出变量 或者常量
js
export const name = "hello";
export let addr = "BeiJing City";
export var list = [1, 2, 3];

或者

js
const name = "hello";
let addr = "BeiJing City";
var list = [1, 2, 3];
export { name, addr, list };
  • 导出函数
js
export function say(content) {
  console.log(content);
}
export function run() {
  console.log("run");
}

或者

js
const say = (content) => {
  console.log(content);
};
let run = () => {
  console.log("run");
};
export { say, run };
  • 导出 Object
js
export ({
      code: 0,
      message: 'success'
  })

或者

js
let data = {
  code: 0,
  message: "success",
};
export { data };
  • 导出 class
js
class Test {
  constructor() {
    this.id = 2;
  }
}
export { Test };

或者

js
export class Test {
  constructor() {
    this.id = 2;
  }
}

as

如果想为输入的变量重新取一个名字,import 命令要使用 as 关键字,将输入的变量重命名。

js
const name = "hello";
let addr = "BeiJing City";
var list = [1, 2, 3];
export { name as cname, addr as caddr, list };

export default

使用 import 命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到 export default 命令,为模块指定默认输出。

js
const name = "hello";
let addr = "BeiJing City";
var list = [1, 2, 3];
export { name as cname, addr as caddr };
export default list;

import

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

直接导入

假设导出模块 A 是这样的

js
const name = "hello";
let addr = "BeiJing City";
var list = [1, 2, 3];
export { name as cname, addr as caddr };
export default list;

则导入

js
import list, {
      cname,
      caddr
  } from A

修改导入名称

js
import list, {
      cname as name,
      caddr
  } from A

批量导入

js
 import list, * as mod from A
  console.log(list)
  console.log(mod.cname)
  console.log(mod.caddr)

推荐阅读