简体   繁体   中英

Node - Why can't imported modules access global variables?

I've recently started using ES6 and properly compartmentalizing my code into multiple files for readability and easier version control and I've run into an issue that I'm not sure is intended, or if I'm missing something.

I have a class stored in a file (class.js) separate from my main script (main.js) and exported via module.exports. In main.js, class.js is required and I use it to create some instances of the class it houses. Inside main.js I have a global variable that is updated regularly, lets say connectedPlayers. Inside one of my methods of class.js I have usersOnline(), which should simply return the value of the global variable connectedPlayers. However, when I try to do this, I get thrown an error that connectedPlayers is not defined. I was under the impression that since the object that calls users.online was defined inside main.js, its usersOnline() method would look for connectedPlayers inside main.js, not class.js... is this correct thinking? If I am correct in that notion then why can't I access connectedPlayers? If I'm not correct in my thinking, how can I access connectedPlayers from inside my class?

Note these are all placeholders and I actually have quite a few global variables in main.js that I need methods inside of class.js to access. These global variables also change regularly so I can't necessarily pass them into the constructor, nor do I want to have to supply them for every call of whatever method I want to use. I'm sure there is a better way to do it, but how?

To clarify even further, the functionality I'm looking to get is similar to how in JS importing works in the browser, once you import your code it acts as if you concatenated that block of code to the code you're importing from. While I understand that's not how it works in node, I thought defining an instance of my class inside the main.js would essentially call the methods from that object (which is in the scope of connectedPlayers), but I guess my understanding is flawed.

Psuedo code:

//class.js
class user{
    constructor(id){
        this.id = id;
    }

    someOtherMethod(){
        ...
    }
    
    usersOnline(){
        this.someOtherMethod(this.id); //here to show I need the context to still be the obj
        return connectedPlayers;
    }
}

//main.js
var user = require('class.js');
var players = {}
var connectedPlayers = 0;

players[id] = new user(id);
console.log(players[id].usersOnline()) //expect to return value of connectedPlayers, but also execute the other function inside of usersOnline properly.

Also, in this example I could simply move the count of players into class.js, but in my actual app I could not do that.

Code would help but assuming I understand this correctly, you have something pseudocode like:

export class Class{
  constructor(){
    this.name = "foo";
  }
  usersOnline(){
   return main.connectedPlayers();
  }
}

-----

require('Class.js');

function connectedPlayers(){
  // stuff...
  return [Object]
}

...
var class1 = new Class();

console.log(class1.name); // correctly gives "foo"
console.log(class1.usersOnline()); // gives main not defined

This is because class.js has no links to the main class. Just because the object is initialized in main.js doesn't mean the object knows what is happening outside it. You need to tell the Object on creation, what it's part of. A common method is to hand down the 'context' of the main class. (mileage will vary)

constructor(context){
  this.name = "foo";
  this.main = context;
}

---

var class1 = new Class(this);

Now on creation the class knows which object is should reference when it's asked to run its usersOnline() function.

Note there are more elegant ways to do this then the method I have listed but the method I'm listing is hopefully indicative of the idea that is generally implemented in more elegant ways See this answer for another method and some more links.

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