模块化(module)

核心思想(ES6 Module)

ES6 模块设计追求静态化编译时就能解析模块依赖、导入导出变量。
对比:CommonJS、AMD 只能在运行时确定依赖关系。

一个模块就是独立文件,文件内变量、函数默认私有,外部无法直接访问;想要对外暴露,必须通过 export 导出,其他文件通过 import 导入。

两大核心指令:
1. export:定义模块对外暴露的接口
2. import:引入其它模块暴露的接口

export 命令

作用:向外提供模块接口,建立接口名与内部变量一一绑定关系

1. 导出变量

方式1:声明时直接导出

export let firstName = 'Michael';
export let lastName = 'Jackson';
export let year = 1958;

方式2:先定义,末尾统一导出(推荐写法
便于集中查看当前模块对外暴露哪些成员

let firstName = 'Michael';
let lastName = 'Jackson';
let year = 1958;

export { firstName, lastName, year };

2. 导出函数 / Class

// 写法1
export function multiply(x, y) {
  return x * y;
}

// 写法2:先定义,统一导出
function add(a, b) {
  return a + b;
}
export { add };

3. 使用 as 重命名导出

对外暴露的名称可以和内部名称不一致

function multiply(x, y) {
  return x * y;
}
// 内部名称multiply,外部导入名称为 multiply2
export { multiply as multiply2 };

4. 重要语法约束

export 导出的是接口绑定关系,不能直接导出字面量值!

//  报错:直接导出数值,不存在接口绑定
export 1;

//  报错:仅仅导出变量的值,不是接口
var m = 1;
export m;

//  正确写法一
export var m = 1;
//  正确写法二
var m = 1;
export { m };
//  正确写法三(重命名导出)
var n = 1;
export { n as m };

函数导出同样遵循该规则:

function f() {}

//  错误
export f;

//  正确
export function f() {}

//  正确
function f() {}
export { f };

5. 实时绑定特性(ES Module关键特性)

ES6 模块导出是动态绑定:外部拿到的是变量引用,模块内部变量更新,外部读取到的值同步更新。

区别 CommonJS:CommonJS 导出的是值拷贝,内部修改不会影响外部。

示例:

// module.js
export let count = 0;
export function inc() {
  count++;
}

// app.js
import { count, inc } from './module.js';
console.log(count); // 0
inc();
console.log(count); // 1 自动更新

6. export 注意事项

  1. export 必须写在模块顶层作用域,不能放在函数、if、for 等代码块内部(静态编译要求)
//  非法
if(true){
  export let a = 1;
}
  1. 同一名称可以重命名导出,但普通命名导出不允许重名接口;
  2. 命名导出和默认导出可以共存。

两种导出模式区分

命名导出(上面全部示例)

export { a, b };
// 导入时必须严格匹配名称
import { a, b } from './xxx.js'

默认导出 export default

一个模块最多只能有一个默认导出

// module.js
export default function(){
  console.log('默认函数');
}

// app.js,导入名称自定义,不需要大括号
import fn from './module.js'

区别:
命名导出:多个,导入需要 {}
默认导出:单个,导入不需要 {}

export * 整体转发(模块代理)

用于中转其它模块接口,常用于聚合模块

// index.js 汇总所有接口向外暴露
export * from './user.js'
// 只转发指定变量
export { getName } from './user.js'