Nodejs 官网的一个循环依赖的例子
a.js
1 | console.log('a starting'); |
b.js
1 | console.log('b starting'); |
index.js
1 | console.log('main starting'); |
运行node index.js后输出顺序如下
1 | main starting |
CommonJS规范的执行逻辑如下
执行 main.js -> main starting
require(‘./a.js’) -> 执行a.js -> a starting
exports.done = false -> 内存中针对a模块对应对象
1
2
3
4
5
6{
id: '模块名a',
exports: {done: false},
loaded: false,
...
}require(‘./b.js’) -> 执行b.js -> a.js代码暂停 -> b starting
exports.done = false; -> 内存中针对b模块对应对象
1
2
3
4
5
6{
id: '模块名b',
exports: {done: false},
loaded: false,
...
}reuqire(‘./a.js’) -> 加载a.js 发生循环依赖 -> a 模块对应的模块对象的exports.done: false -> in b, a.done = false
继续执行b.js exports.done = true -> b done
1
2
3
4
5
6{
id: '模块名b',
exports: {done: true},
loaded: true,
...
}继续执行a.js -> in a, b.done = true
执行 a.js exports.done = true -> b done
1
2
3
4
5
6{
id: '模块名a',
exports: {done: true},
loaded: true,
...
}main.js in main, a.done = true, b.done = true
CommonJS规范如何处理循环加载
CommonJS模块的重要特性就是加载时执行, 当脚本require时, 就会全部执行; 并且在内存中生成一个对象, 遇到某个模块循环加载, 则只输出已经执行的部分, 还未执行的部分不会输出.
reuqire()源码解读
http://www.ruanyifeng.com/blog/2015/05/require.html
1 | { |
webpack 对require 的编译如下:
1 | (function(modules) { |