前言
之前面试的时候,遇到这玩意两次,特别的感人和无奈
a文件的执行依赖于b文件,b文件的执行依赖于a文件
require和import互相导入文件————其实就是模块循环加载
正文
理论区别
ES6
ES6模块规范是使用import导入模块,export导出模块,输出的是对值的引用,因为是引用,所以会被影响。
模块导入是当遇到模块加载命令import时先不去执行这个模块,而是生成一个引用,等到调用这个值时,再到模块中取值,有点类似浅拷贝,如果原始值变了,那输入值也会发生改变。
CommonJS
CommonJS模块规范是require语句导入模块,module.exports导出模块,输出的是值的拷贝
模块导入的是输出值的拷贝,一旦输出这个值,这个值就与模块没有关系了,这个值在模块内部的变化是监听不到的。
模块循环加载的区别
产生模块循环加载,模块就是一个js文件,a,b两个js文件相互依赖,a导入b,b导入a, 最终到一起导入main.
CommonJS
案例来源于node官方:nodejs.org/api/modules…
//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执行完毕!')
//b.js
exports.done = false;
var a = require('./a.js');
console.log('在b.js中,a.done ='+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 ='+a.done,'在main.js中,b.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
执行流程
1、在main.js文件里按顺序执行,先执行a文件,看到a.js
2、a文件导出done为false,然后执行b文件,a文件后面不再执行,看到b.js
3、导出done仍为false,又再次回到a文件,之前执行过不再执行,相当于a文件就只执行了done.false就回到b.js文件中
4、所以再来就打印,b.js中,a.done = false,导出的done为true,b.js执行完毕!
5、再来就回到a.js文件,打印,在a.js中,b.done = true
6、导出done为true,a.js执行完毕!
7、回到main.js,第二行不会在执行b文件,而是直接输出缓存结果
8、打印在main.js中,a.done = true, b.done = true
总结
在循环加载中,只输出执行的部分,如a文件没执行完,只输出了done=false 第二次执行会直接走缓存
ES6
//a.js
import {b} from './b';
var counter = 0;
export function a(n){
counter ++;
console.log(counter);
return n == 0 || b(n-1);
}
//b.js
import {a} from './a.js';
export function b(m){
return n != 0 && a(m-1);
}
//index.js
import * as m from './a.js';
var x = m.a(5);
console.log(x);
var y = m.a(4);
console.log(y);
输出结果
1
2
3
false
4
5
6
true
执行流程
counter
a(5) 1 b(4)
a(3) 2 b(2)
a(1) 3 b(0)
false
a(4) 4 b(3)
a(2) 5 b(1)
a(0) 6
true
总结
可以看出counter值是累加的