简体   繁体   中英

How to Call Global Variables From Constructors

I have a class that looks like this:

class MyClass {

    constructor() {
        this.field = 42;
    }
    
    method() {
        return "Hello world!";
    }
}

I want to define an instance of it as a global variable, so I registered it:

global.MyObject= new MyClass();

Which means this will now work:

console.log(MyObject.field); // 42
console.log(MyObject.method()); // Hello world!

However, whenever I call that same code from another class it suddenly becomes a lot more random:

class OtherClass {

    constructor() {
        console.log(MyObject.field); // undefined
        console.log(MyObject.method()); // TypeError: MyObject.method is not a function
    }
}

Sometimes this works, sometimes it doesn't. I am not able to find out when it works and when it doesn't, only that it isn't totally random. Called from the same place, the constructor either works or not. Which does not help to isolate the problem.

It seems that when the class's constructor is called from a module that does not have a direct require('my-class') it will not work - even when OtherClass has that requironment? Even when every other module has that require ? Which does not make any sense.

I tried it with two modules A and B. If A defines global variables, B can access them just fine even without a require - as long as someone else has it.

So... I'm stumped at how this works. Might be a silly JavaScript gimmick, I'm not a native JavaScript developer.

My setup looks like this:

  • src/
    • ActualCode (uses functionality that will create OtherClass )
  • test/
    • mock/
      • MyClass
      • OtherClass ( require('MyClass') )
    • ActualCodeTest ( require('ActualCode') , require('OtherClass')

The constructor in OtherClass will be able to access MyClass when called from MyClass and OtherClass , but not from ActualCode or ActualCodeTest . Even if called in sequence (so the global variable definitively exists).

Which means changing parameters and adding a require is out of the question, since the ActualCode should never know test code.

The problem seems to be with the Mocha framework. The global variable cannot be accessed inside the "it":

console.log(MyObject.field); // 42

it('test', () => {
    console.log(MyObject.field); // undefined
}

If I remove the surrounding code it will (obviously) work.

How do I call global variables from a class's constructor?

This sample code works as expected when you have it all in a single file:

$ cat sample.js 
class MyClass {
    constructor() {
        this.field = 42;
    }

    method() {
        return "Hello world!";
    }
}
global.MyObject = new MyClass();

class OtherClass {
    constructor(props) {
        console.log(MyObject.field);
        console.log(MyObject.method());
    }
}

new OtherClass();
$ node sample
42
Hello world!

I suspect the confusion comes in the sequence those lines are run when you're loading the modules. Node's module-loading code will run every line in the sequence they are encountered.

The problem is that Mocha can't access global variables in its tests. I could not find the relevant bug for this behavior, but at least a person with the same problem .

Since the global variables are only used in the tests, I get to have an easy solution:

global.MyObject= new MyClass();

module.exports.MyObject = MyObject;

And this in the test:

before(() => {
    global.MyObject = require('./mock/my-class').MyObject;
});

It's probably a good idea to add a TODO so you can revisit this issue every now and then in case the Mocha crew fixes it.

I have a class that looks like this:

class MyClass {

    constructor() {
        this.field = 42;
    }
    
    method() {
        return "Hello world!";
    }
}

I want to define an instance of it as a global variable, so I registered it:

global.MyObject= new MyClass();

Which means this will now work:

console.log(MyObject.field); // 42
console.log(MyObject.method()); // Hello world!

However, whenever I call that same code from another class it suddenly becomes a lot more random:

class OtherClass {

    constructor() {
        console.log(MyObject.field); // undefined
        console.log(MyObject.method()); // TypeError: MyObject.method is not a function
    }
}

Sometimes this works, sometimes it doesn't. I am not able to find out when it works and when it doesn't, only that it isn't totally random. Called from the same place, the constructor either works or not. Which does not help to isolate the problem.

It seems that when the class's constructor is called from a module that does not have a direct require('my-class') it will not work - even when OtherClass has that requironment? Even when every other module has that require ? Which does not make any sense.

I tried it with two modules A and B. If A defines global variables, B can access them just fine even without a require - as long as someone else has it.

So... I'm stumped at how this works. Might be a silly JavaScript gimmick, I'm not a native JavaScript developer.

My setup looks like this:

  • src/
    • ActualCode (uses functionality that will create OtherClass )
  • test/
    • mock/
      • MyClass
      • OtherClass ( require('MyClass') )
    • ActualCodeTest ( require('ActualCode') , require('OtherClass')

The constructor in OtherClass will be able to access MyClass when called from MyClass and OtherClass , but not from ActualCode or ActualCodeTest . Even if called in sequence (so the global variable definitively exists).

Which means changing parameters and adding a require is out of the question, since the ActualCode should never know test code.

The problem seems to be with the Mocha framework. The global variable cannot be accessed inside the "it":

console.log(MyObject.field); // 42

it('test', () => {
    console.log(MyObject.field); // undefined
}

If I remove the surrounding code it will (obviously) work.

How do I call global variables from a class's constructor?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM