- 介绍
- es6中模块化思想是尽量静态化,编译时确定模块依赖关系与输入输出
- CommonJS(CMD)与AMD都只能在运行时确定
- UMD模式只是加了CMD和AMD的切换
- ECMAScript 6
- 特点
- import, export可以出现在顶层的任何位置
- import
- 会变量提升, 会执行import的模块
- 引入的变量是只读的,修改会报错。但可以修改引入变量的内部属性
- 只加载3个方法,编译时加载,可能静态分析。但不能引用fs模块本身
- 使引入宏(macro)和类型检查(type system)成为可能
- 模块自动采用严格模式
- 输出/引入的是值的只读引用, 值在运行时计算
- import
- import {stat, exists, readFile} from ‘fs’ # 多引用
- import {a as b} from ‘./profile’ # b 作为 a 的别名
- import ‘lodash’ # 只运行模块
- import * as circle from ‘./circle’ # 引入模块到对象
- import a from ‘./export-default’ # 引入模块中默认的导出, a可以起任意名,不用大括号
- import {default as xxx} from ‘./’ # 本质是输出名字为default变量
- import def, {a} from ‘./module’ # 同时引入default和其它变量
- export
- export var a = 1;
- export function f () {}
- var b = 1, c = 1;
- export {b, c} # 用于统一输出
- export {v1 as sv1}
- export {a as b} from ‘./someModule’ # 导入同时导出
- export v from ‘mod’ # 导入同时导出, es7提案可省略大括号
- export default function() {} # export default命令来配置默认导出, 本质是输出名字为default的变量,系统允许它取任意名
- export default foo 导出的foo名在模块外部是无效
- 继承
- export * from ‘circle’
- export var e = 2.7
- export default function() {} # 输出了circle模块的所有方法(忽略default), 又输出了自定义属性
- 循环引用
- CommonJS会输出已执行的部分
- 写法问题
- var foo = require(‘a’).foo
- a在别处循环引用时, 得到的foo可能是执行到一半的值
- 而var a = require(‘a’), a.foo就会得到执行完后的值
- 例子
-
a.js
exports.done = false;
var b = require('./b.js');
console.log('a.js => b.done : ', b.done)
exports.done = true;
console.log('a.js done')
b.js
exports.doen = false;
var a = require('./a.js')
console.log('b.js => a.done : ', a.done);
exports.done = true;
console.log('a.js done')
main.js
var a = require('./a.js'), b = require('./b.js')
console.log('main.js => a.done: ', a.done, ' b.done: ', b.done)
执行
b.js => a.done: false
b.js done
a.js => b.done: true
a.js done
main.js => a.done: true b.done: true
a.js中require('./b.js')阻塞, 执行b.js
b.js中require('./a.js'), 加载已执行的a.js
执行完b.js回到a.js, 执行完a.js
main.js加载已执行的a.js b.js
- ES6 import时不执行代码,而是引用
-
例子
CommonJS中不能执行, a加载b, b加载a, a没有输出, foo不存在, es6中可以执行
a.js
import {bar} from './b.js';
export function foo() {
bar();
console.log('a.js done')
}
b.js
import {foo} from './a.js';
export function bar() {
if(Math.random() > 0.5) {foo()}
}
babel-node a.js
例子
even.js
import {odd} from './odd'
export var counter = 0;
export function even(n) {
counter++;
return n == 0 || odd(n - 1);
}
odd.js
import {even} from './even';
export function odd(n) {
return n != 0 && even(n - 1);
}
main.js
import * as m from './even.js'
m.even(10) // true
m.counter // 6 # 10 变到 0 even执行了6次
m.even(20) // true # 20 变到 0 even执行了11次
m.counter // 17 #es6中引用加载机制保证even, odd函数能加载,所以可执行。而CommonJS中循环引用,even和odd函数都不会加载