首页 > 为什么这段 node.js 循环引用的代码片段可以正常工作?

为什么这段 node.js 循环引用的代码片段可以正常工作?

A 模块代码:

console.log(' 开始加载 A 模块');
var b = require('./b.js');
console.log('in a, b is ', b);

exports.func = function() {
  console.log('调用 A 模块成功');
};

console.log('A 模块加载完毕');

B 模块代码:

console.log(' 开始加载 B 模块');
var A = require('./a.js');
console.log('in b, a is ', A);

exports.callAmodule = function() {
  A.func();
}
console.log('B 模块加载完毕');

运行如下代码,先加载 A 模块,制造循环引用:

var a = require('./a.js');
var b = require('./b.js');
b.callAmodule();

运行结果如下:

开始加载 A 模块
开始加载 B 模块
in b, a is  {}
B 模块加载完毕
in a, b is  { callAmodule: [Function] }
A 模块加载完毕
调用 A 模块成功

两个模块产生循环引用,执行时:B 模块中的 A 是没加载完全的。但是 callAmodule 方法却成功执行了 A 模块的方法,这不符合我的预期,另外一段类似的循环引用,的确产生了问题,是符合我预期的代码见: http://selfcontained.us/2012/...

不清楚两段类似的循环引用代码,却结果完全不一样的原因


当main.js加载a.js的时候,a.js依次需要加载b.js.在这时,b.js试着去加载a.js.为了防止一个无穷的循环(loop),一个未完成的a.js的副本的exports导出对象被返回到b.js模块.然后b.js完成加载,然后他的exports导出对象被提供给a.js模块.
看这个,因为你这里a.js 和a.js都有一个exports
http://blog.csdn.net/kingvike...


1、加载和执行不同
2、加载模块是“同步”的


你把A模块里的代码改成下面这样就会出现预期的报错:

module.exports = {
  func: function () {
    console.log('调用 A 模块成功');
  }
};

理解这一点需要明白 exports 和 module.exports 的区别:

  1. exports 是指向的 module.exports 的引用

  2. module.exports 初始值为一个空对象 {},所以 exports 初始值也是 {}

  3. require() 返回的是 module.exports 而不是 exports

在 A 模块还没有加载完时,就开始加载 B 模块,此时,var a = require('./a.js') 返回的 A 模块的 module.exports 是 {}。B 模块加载完成后,继续回到 A 模块完成 A 模块的加载。

如果在 A 模块里,通过 exports.func 来定义方法,就会动态地给 A 模块的 module.exports 加入 func 方法,后边 A.func()调用该方法时,是没有问题的。

如果在 A 模块里,用 module.exports = { func: ...} 方式来定义方法,由于加载 B 模块时,var a = require('./a.js') 已经返回 A 模块的 module.exports 是 {},后边加载完 B 模块后再继续加载 A 模块也不会改变 A 模块导出的值为 {},所以,调用A.func() 就会出现 TypeError: A.func is not a function 的报错。

【热门文章】
【热门文章】