require和import互相导入文件

702 阅读2分钟

前言

之前面试的时候,遇到这玩意两次,特别的感人和无奈

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值是累加的