es6
版本引进的模块化方案,相当于结构赋值
commonjs
模块化方案,最初在nodejs
中使用,相当于值拷贝
import
是编译时输出,静态,输出的是值的引用,内存地址相同require
在运行时加载,是动态的,输出的是值的拷贝,内存地址不同
// count.js
exports.count = 1;
setTimeout(() => {
console.log('incre count', ++exports.count);
}, 1000);
import count from './count';
console.log('es-moudle', count);// 1
setTimeout(() => {
console.log('es-module after', count);// 2
}, 2000);
// commonjs.js
const { count } = require('./count');
// const a = require('./esm-export');
console.log('cjs', count); //1
setTimeout(() => {
console.log('cjs after', count);// 1
}, 2000);
commmonjs
循环引用只会引入已经执行的部分,等引入部分执行完后,在继续往下执行
// a.js
exports.done = false;
var b = require('./b.js');
console.log('在 a.js 之中,b.done = %j', b.done);
exports.done = true;
console.log('a.js 执行完毕');
// b.js
exports.done = false;
var a = require('./a.js');
console.log('在 b.js 之中,a.done = %j', a.done);
exports.done = true;
console.log('b.js 执行完毕');
// main.js
var a = require('./a.js');
var b = require('./b.js');
console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);
// 在 b.js 之中,a.done = false
// b.js 执行完毕
// 在 a.js 之中,b.done = true
// a.js 执行完毕
// 在 main.js 之中, a.done=true, b.done=true
过程:
main.js
执行第一行,引入a.js
- 执行
a.js
输出done=false
执行到第二行引入b.js
,开始执行b.js
b.js
引入a.js
,循环引用,只引入a.js
已经执行的部分exports.done = false;
,输出a.done=false
,继续往下执行b.js
执行完毕,回到a.js
继续执行,此时输出b.done=true
,执行完毕a.js
执行完毕,回到main.js
,忽略第二行,输出缓存中的a=true
和b=true
es modules
循环引用在定义之前使用,可能会报错
// bar.js
import { foo } from './foo'
console.log(foo);
export let bar = 'bar'
// foo.js
import { bar } from './bar'
console.log(bar);
export let foo = 'foo'
// main.js
import { bar } from './bar'
console.log(bar)
过程:
main.js
引入bar
bar.js
引入foo
foo.js
引入bar
,没有找到bar
定义,输出undefined
- 回到
bar.js
输出foo
- 回到
main.js
输出bar