Java Script - 循环加载
循环加载指的是:a 在执行时依赖 b, b 的执行同时也依赖 a
一、Common Js 循环加载机制
做法:一旦某个模块出现 “循环加载”,只输出执行部分,未执行部分暂时不输出。
a.js
exports.done = false;
var b = require('./b.js');
console.log(`Work in a.js, the value of b.done is ${b.done}`);
exports.done = true;
console.log(`a.js works finish`);
b.js
exports.done = false;
var a = require('./a.js');
console.log(`Work in b.js, the value of b.done is ${a.done}`);
exports.done = true;
console.log(`b.js works finish`);
a 中 require('./b.js') 加载了 b , b 中也require('./a.js') 加载了a。两个模块形成了循环加载。
main.js
var a = require('./a.js'); var b = require('./b.js'); console.log('Work in main.js, a.done=%j, b.done=%j', a.done, b.done);
main.js 运行步骤:
(1) a 在运行到第二行时,开始加载 b, a 在第二行之后暂时不再执行,a中的done = false。
(2) 带入到b中,b开始执行,b中的 a.done 就等于 false,b执行到最后,b中的done = true。
(3) 再回到a,a继续执行,a中的b.done就是true。
执行结果
$ node main.js Work in b.js, the value of b.done is false b.js works finish Work in a.js, the value of b.done is true a.js works finish Work in main.js, a.done=true, b.done=true
二、ES6 循环加载
做法:ES6 和 CommonJS 的做法不一样,ES6 在遇到加载命令 import 时,不会直接执行引用的模块,而是生成一个引用,等到应用到加载的模块时,再到加载模块中进行取值。
ES6的模块是动态引用,也就是说不会缓存对引用的数据,而是在使用的时候直接动态的获取。
// a.js import { nodeB } from './b.js' export function nodeA() { nodeB(); console.log("Works finish") } nodeA(); // b.js import { nodeA } from './a.js' export function nodeB() { nodeA(); }
如果是 CommonJs 上面的这组代码将会报错。因为 a 中第一行就加载了 b, 系统会先执行模块b,b又加载了a,但是模块a中第一行之后不会执行,所以模块b的加载a操作会报错。
但是在 ES6 中,加载只是会生成一个引用,只有引用被使用时,才会需要在加载模块中获得时,模块b就可以正常运行了。