我最近一直在使用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的实例。

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


当前回答

你可以很容易地解决这个问题:在你需要使用module.exports的模块中任何其他东西之前,只需导出你的数据:

classA.js

class ClassA {

    constructor(){
        ClassB.someMethod();
        ClassB.anotherMethod();
    };

    static someMethod () {
        console.log( 'Class A Doing someMethod' );
    };

    static anotherMethod () {
        console.log( 'Class A Doing anotherMethod' );
    };

};

module.exports = ClassA;
var ClassB = require( "./classB.js" );

let classX = new ClassA();

classB.js

class ClassB {

    constructor(){
        ClassA.someMethod();
        ClassA.anotherMethod();
    };

    static someMethod () {
        console.log( 'Class B Doing someMethod' );
    };

    static anotherMethod () {
        console.log( 'Class A Doing anotherMethod' );
    };

};

module.exports = ClassB;
var ClassA = require( "./classA.js" );

let classX = new ClassB();

其他回答

如果你不能消除循环依赖(例如useraccount <——> userlogin),还有一个选择…

它就像使用setTimeout()一样简单

//useraccount.js

let UserLogin = {};

setTimeout(()=>UserLogin=require('./userlogin.js'), 10);

class UserAccount{
 
getLogin(){
return new UserLogin(this.email);

}

}



//userlogin.js

let UserAccount ={};

setTimeout(()=>UserAccount=require('./useraccount.js'), 15);


class UserLogin{

getUser(){

return new User(this.token);

}

}

最简单的解决方法通常是:

通常你会把要求放在文件的顶部…

var script = require('./script')
function stuff() {
      script.farfunction()
}

相反,只需“在函数中”要求它

function stuff() {
      var _script = require('./script')
      _script.farfunction()
}

博士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

这里有一个快速的解决方法,我发现它非常有用。

在文件a.js上

let B;
class A{
  constructor(){
    process.nextTick(()=>{
      B = require('./b')
    })
  } 
}
module.exports = new A();

在文件'b.js'上写以下内容

let A;
class B{
  constructor(){
    process.nextTick(()=>{
      A = require('./a')
    })
  } 
}
module.exports = new B();

这样,在事件循环的下一次迭代中,类将被正确定义,并且那些require语句将按预期工作。