# ES6-模块详解

# 编译时静态检查

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

// 错误:由于不是编译时检查,所以这种方式会报错,而commonjs就不会
// 所以使用import和export都会放在最外层,而允许放在arr.forEach(key => import * from key)中
let modulePath = './test'
import test from modulePath

// 正确
import test from './test'

# es6 module和commonjs不同

  1. es6 module编译时输出接口,commonjs运行时加载。
  2. es6 module输出引用,commonjs输出拷贝。
  3. 循环引用处理不同。es6 module生成指向,内容自己保证;commonjs只输出已执行部分(说到底还是输出拷贝)。

由于动态加载非常实用,故tc39引入了import() (opens new window)提案,帮动态加载模块

# export 几种用法

export命令用于规定模块的对外接口

// 使用export {}不能使用import {name1, name2, …} from '...'方式导入
export { name1, name2,, nameN };
export { variable1 as name1, variable2 as name2,, nameN };

// export type方式
// 使用export type才是import {name1, name2, …} from '...'的正确使用方式
export let name1, name2,, nameN;
export let name1 =, name2 =,, nameN;
export function FunctionName() {...}
export class ClassName {...}

// export default 方式。 default、 as 关键字
export default expression;
export default function () {}
export default function name1() {}
export { name1 as default,}; // 等价于export default name1, ...

// 模块继承,导入和导出在一行。
// 这种方式非常适合重构时,帮助把大文件拆分成多个小文件
export * from;
export { name1, name2,, nameN } from;
export { import1 as name1, import2 as name2,, nameN } from;

# import 几种用法

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

// export default 方式
import defaultName from 'modules.js';

// export type 方式
import { export1, export2 } from 'modules';
import { export1 as ex1, export2 as ex2 } from 'moduls.js'; // as 关键字
import * as moduleName from 'modules.js';

// 同时引入export default 和export type
import defaultName, { expoprt1, export2 } from 'modules';
import defaultName, * as moduleName from 'modules';

// 引入无输出模块
import 'modules';

# 参考文章