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

查看:133
本文介绍了为什么这段 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/...

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

解决方案

你把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 的报错。

这篇关于为什么这段 node.js 循环引用的代码片段可以正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆