我最近一直在使用nodejs,仍然在掌握模块系统,所以如果这是一个明显的问题,那么很抱歉。我希望代码大致如下:

A.js(主文件与node一起运行)

var ClassB = require("./b");

var ClassA = function() {
    this.thing = new ClassB();
    this.property = 5;
}

var a = new ClassA();

module.exports = a;

b.js

var a = require("./a");

var ClassB = function() {
}

ClassB.prototype.doSomethingLater() {
    util.log(a.property);
}

module.exports = ClassB;

我的问题似乎是我不能从ClassB的实例中访问ClassA的实例。

有什么正确的/更好的方法来构建模块来实现我想要的? 是否有更好的方法在模块间共享变量?


当前回答

虽然node.js确实允许循环的require依赖关系,但你已经发现它可能非常混乱,你最好重新构造你的代码以不需要它。也许可以创建第三个类,使用另外两个类来完成您所需要的。

其他回答

事实上,我最终需要我的依赖

 var a = null;
 process.nextTick(()=>a=require("./a")); //Circular reference!

虽然不漂亮,但很管用。这比更改b.js(例如只增加modules.export)更容易理解和诚实,因为后者是完美的。

虽然node.js确实允许循环的require依赖关系,但你已经发现它可能非常混乱,你最好重新构造你的代码以不需要它。也许可以创建第三个类,使用另外两个类来完成您所需要的。

尝试在模块上设置属性。出口,而不是完全取代它。例如,module.exports.instance = a.js中的新ClassA(), module.exports.ClassB = b.js中的ClassB。当你创建循环模块依赖关系时,需要的模块将得到一个不完整模块的引用。从所需的模块导出,您可以稍后添加其他属性,但当您设置整个模块时。导出,你实际上创建了一个新对象,所需的模块没有办法访问。

博士TL;

只需使用导出。somember = somember而不是module。Exports ={//新对象}。

扩展的回答

在读完lanzz的回答后,我终于可以弄清楚这里发生了什么,所以我会就这个问题发表我的意见,扩展他的回答。

让我们来看看这个例子:

a.js

console.log("a starting");

console.log("a requires b");
const b = require("./b");
console.log("a gets b =", b);

function functionA() {
  console.log("function a");
}

console.log("a done");
exports.functionA = functionA;

b.js

console.log("b starting");

console.log("b requires a");
const a = require("./a");
console.log("b gets a =", a);

function functionB() {
  console.log("On b, a =", a)
}

console.log("b done");
exports.functionB = functionB;

main.js

const a = require("./a");
const b = require("./b");

b.functionB()

输出

a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = { functionA: [Function: functionA] }

在这里,我们可以看到b首先接收一个空对象作为a,然后一旦a完全加载,该引用将通过导出更新。functionA = functionA。如果将整个模块替换为另一个对象,则通过module。导出,那么b将失去来自a的引用,因为它将从开始指向相同的空对象,而不是指向新的对象。

如果你像这样导出:module。exports = {functionA: functionA},那么输出将是:

a starting
a requires b
b starting
b requires a
b gets a = {}
b done
a gets b = { functionB: [Function: functionB] }
a done
On b, a = {} // same empty object

有时引入第三个类(JohnnyHK建议)确实是人为的,所以除了Ianzz之外: 如果您确实需要更换模块。导出,例如,如果你正在创建一个类(如上面例子中的b.js文件),这也是可能的,只要确保在开始循环require的文件中,'模块。出口=…`语句发生在require语句之前。

A.js(主文件与node一起运行)

var ClassB = require("./b");

var ClassA = function() {
    this.thing = new ClassB();
    this.property = 5;
}

var a = new ClassA();

module.exports = a;

b.js

var ClassB = function() {
}

ClassB.prototype.doSomethingLater() {
    util.log(a.property);
}

module.exports = ClassB;

var a = require("./a"); // <------ this is the only necessary change