节点-为什么导入的模块无法访问全局变量?

时间:2020-07-13 06:24:21

标签: javascript node.js class import global-variables

我最近开始使用ES6,并将我的代码正确划分为多个文件以提高可读性和更容易的版本控制,但遇到了一个不确定的问题,或者是否缺少某些内容。< / p>

我有一个类存储在与主脚本(main.js)分开的文件(class.js)中,并通过module.exports导出。在main.js中,class.js是必需的,我用它来创建它所容纳的类的一些实例。在main.js内部,我有一个定期更新的全局变量,可以说connectedPlayers。在我的class.js方法之一中,我有usersOnline(),它应该简单地返回全局变量connectedPlayers的值。但是,当我尝试执行此操作时,会引发未定义connectedPlayers的错误。我给人的印象是,由于调用users.online的对象是在main.js中定义的,因此它的usersOnline()方法将在main.js而不是class.js中查找connectedPlayers ...这是正确的想法吗?如果我在这个概念上是正确的,那为什么我不能访问connectedPlayers?如果我的想法不正确,该如何从班级内部访问connectedPlayers?

请注意,这些都是占位符,实际上在main.js中我有很多全局变量,我需要在class.js内部访问方法。这些全局变量也会定期更改,因此我不必将它们传递到构造函数中,也不必为每次要使用的方法的每次调用提供它们。我敢肯定有更好的方法可以做到,但是怎么办?

为进一步阐明,我希望获得的功能类似于JS导入在浏览器中的工作方式,一旦导入代码,它的行为就好像是将该代码块连接到要导入的代码一样从。虽然我知道这不是节点中的工作原理,但我认为在main.js中定义类的实例实际上会从该对象中调用方法(属于connectedPlayers的范围),但我想我的理解是有缺陷的。

伪代码:

//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.

此外,在此示例中,我可以将玩家数量简单地移到class.js中,但是在我的实际应用中,我无法做到这一点。

1 个答案:

答案 0 :(得分:1)

代码会有所帮助,但假设我正确理解了这一点,您就会得到类似以下的伪代码:

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

这是因为class.js没有指向主类的链接。仅仅因为在main.js中初始化了对象并不意味着该对象知道其外部发生了什么。您需要在创建时告诉对象,对象是对象的一部分。一种常见的方法是传递主类的“上下文”。 (里程会有所不同)

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

---

var class1 = new Class(this);

现在,在创建类时,该类知道当要求其运行usersOnline()函数时应该引用哪个对象。

请注意,比我列出的方法还有更优雅的方法来执行此操作,但希望我列出的方法表明通常以更优雅的方式See this answer来实现另一种方法的想法。链接。