Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否可以将全局作用域注入ES6中的实例化类(也称为singleton)?_Javascript_Node.js_Ecmascript 6 - Fatal编程技术网

Javascript 是否可以将全局作用域注入ES6中的实例化类(也称为singleton)?

Javascript 是否可以将全局作用域注入ES6中的实例化类(也称为singleton)?,javascript,node.js,ecmascript-6,Javascript,Node.js,Ecmascript 6,首先我需要道歉,因为这里面会有很多代码,这会让这个问题变得臃肿。然而,我认为这将有助于更好地理解我的问题 假设我有一个给定的main模块: 'use strict'; /** * Loads Module from given name. * @class {LoadModules} */ class LoadModules { constructor(moduleName) { // define Modulename. this.moduleName = mod

首先我需要道歉,因为这里面会有很多代码,这会让这个问题变得臃肿。然而,我认为这将有助于更好地理解我的问题

假设我有一个给定的
main模块

'use strict';

/**
 * Loads Module from given name.
 * @class {LoadModules}
 */
class LoadModules {

  constructor(moduleName) {
    // define Modulename.
    this.moduleName = moduleName;
  }

  /**
   * Initialize module.
   * @method init
   * @return {void} [nothing]
   */
  init() {

    // Path Module.
    const path = require('path');

    // Require Module from given Name.
    let ModuleToLoad = require(path.join(__dirname, 'Modules', this.moduleName, this.moduleName + '.js'));
    // Instatiate Module.
    ModuleToLoad = new ModuleToLoad();
    // Start module.
    ModuleToLoad.init();
  }

}
/**
 * This is a Module which can be loaded by the MainModule.
 * @class {ModuleToBeLoaded}
 */
module.exports = class ModuleToBeLoaded {

  constructor() {
    /**
     * Empty
     */
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    console.log('module Loaded');
  }

};
// This is in the global scope.
const LoggerClass = new Logger();
/**
* LoadModule class stuff comes after this.
*/
以及可加载到
main模块中的其他模块

'use strict';

/**
 * Loads Module from given name.
 * @class {LoadModules}
 */
class LoadModules {

  constructor(moduleName) {
    // define Modulename.
    this.moduleName = moduleName;
  }

  /**
   * Initialize module.
   * @method init
   * @return {void} [nothing]
   */
  init() {

    // Path Module.
    const path = require('path');

    // Require Module from given Name.
    let ModuleToLoad = require(path.join(__dirname, 'Modules', this.moduleName, this.moduleName + '.js'));
    // Instatiate Module.
    ModuleToLoad = new ModuleToLoad();
    // Start module.
    ModuleToLoad.init();
  }

}
/**
 * This is a Module which can be loaded by the MainModule.
 * @class {ModuleToBeLoaded}
 */
module.exports = class ModuleToBeLoaded {

  constructor() {
    /**
     * Empty
     */
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    console.log('module Loaded');
  }

};
// This is in the global scope.
const LoggerClass = new Logger();
/**
* LoadModule class stuff comes after this.
*/
正如您所看到的,这是用来动态加载模块的,它工作得非常好

我的问题是,动态加载其他模块的
MainModule
无法在模块之间共享自己的全局范围,或者至少我不知道如何实现。我很清楚这很复杂,因为我的
main模块
ModuleToBeLoaded
在不同的文件中

例如,我的
main模块的全局范围中有一个
LoggerClass

'use strict';

/**
 * Loads Module from given name.
 * @class {LoadModules}
 */
class LoadModules {

  constructor(moduleName) {
    // define Modulename.
    this.moduleName = moduleName;
  }

  /**
   * Initialize module.
   * @method init
   * @return {void} [nothing]
   */
  init() {

    // Path Module.
    const path = require('path');

    // Require Module from given Name.
    let ModuleToLoad = require(path.join(__dirname, 'Modules', this.moduleName, this.moduleName + '.js'));
    // Instatiate Module.
    ModuleToLoad = new ModuleToLoad();
    // Start module.
    ModuleToLoad.init();
  }

}
/**
 * This is a Module which can be loaded by the MainModule.
 * @class {ModuleToBeLoaded}
 */
module.exports = class ModuleToBeLoaded {

  constructor() {
    /**
     * Empty
     */
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    console.log('module Loaded');
  }

};
// This is in the global scope.
const LoggerClass = new Logger();
/**
* LoadModule class stuff comes after this.
*/
我希望所有模块都能像访问自己的全局范围一样访问LoggerClass,而无需在每个模块中反复定义它。例如,我将
ModuleToBeLoaded
类中的
console.log
更改为:

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    LoggerClass.log('module Loaded');
  }
所以基本上我在
main模块中定义了Globals,我想在
ModuleToBeLoaded
的代码中访问这些Globals。一种可能的解决方案是更改
模块中的
构造函数
。像这样:

  constructor(LoggerClass) {
    // Here I can set LoggerClass internally.
    this.LoggerClass = LoggerClass;
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    this.LoggerClass.log('module Loaded');
  }
这可以让我像这样实例化这个类:

// Instatiate Module.
ModuleToLoad = new ModuleToLoad(LoggerClass);
这是正确的方法,还是有其他更好的解决方案

我想要实现的是ES6中已知的模式
singelton模式
。 有关更多信息,请查看此Wiki页面:


旁注:我在一个没有任何第三方库的
nodejs7.10.0
环境中

问候,,
Megajin

LoggerClass.js这就是您制作单例的方式(始终是同一个实例)

LoadModules.js

const getLoggerClass = require('./LoggerClass');

module.exports = class LoadModules {
  constructor(moduleName) {
    this.moduleName = moduleName;
  }

  init() {
    const path = require('path');
    // changed the require statement, to make it simpler
    let ModuleToLoad = require(path.join(__dirname, this.moduleName + '.js'));
    ModuleToLoad = new ModuleToLoad(getLoggerClass());
    ModuleToLoad.init();
  }
}
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded module Loaded');
    this.logger.log();
  }
};
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded2 module Loaded');
    this.logger.log();
  }
};
ModuleToLoad.js

const getLoggerClass = require('./LoggerClass');

module.exports = class LoadModules {
  constructor(moduleName) {
    this.moduleName = moduleName;
  }

  init() {
    const path = require('path');
    // changed the require statement, to make it simpler
    let ModuleToLoad = require(path.join(__dirname, this.moduleName + '.js'));
    ModuleToLoad = new ModuleToLoad(getLoggerClass());
    ModuleToLoad.init();
  }
}
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded module Loaded');
    this.logger.log();
  }
};
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded2 module Loaded');
    this.logger.log();
  }
};
ModuleToLoad2.js

const getLoggerClass = require('./LoggerClass');

module.exports = class LoadModules {
  constructor(moduleName) {
    this.moduleName = moduleName;
  }

  init() {
    const path = require('path');
    // changed the require statement, to make it simpler
    let ModuleToLoad = require(path.join(__dirname, this.moduleName + '.js'));
    ModuleToLoad = new ModuleToLoad(getLoggerClass());
    ModuleToLoad.init();
  }
}
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded module Loaded');
    this.logger.log();
  }
};
module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded2 module Loaded');
    this.logger.log();
  }
};
演示

> node
> const LoadModules = require('./LoadModules');
> var load = new LoadModules('ModuleToLoad');
> var load2 = new LoadModules('ModuleToLoad2');

> load.init();
ModuleToBeLoaded module Loaded
logging secret instance: 1495528699144
> load2.init();
ModuleToBeLoaded2 module Loaded
logging secret instance: 1495528699144
正如您所注意到的,根据LoggerClass的
this.instanceData
,实例是相同的


删除注释以使代码更精简

我觉得奇怪的是,您有一个单独的
构造函数
init
。为什么不在构造函数中进行初始化呢

无论如何,似乎正确的方法确实是将“全局”传递给要加载的模块的构造函数或init


如果你真的希望它是一个全局的,你可以将它添加到
global
名称空间。

为什么你有一个构造函数和一个init方法?
init()
是启动我的模块,它可以被称为
start
或其他任何东西。然而,ES6规范中有
constructor
,请看这里:所以您希望
LoggerClass
是单例的(所有要加载的模块都是同一个实例)?谢谢,但您不能使用构造函数并删除init吗?@medttleucully是的。我想通过将要加载的每个模块访问
LoggerClass
,而无需在每个模块中反复实例化它。我需要这两种方法,因为构造函数将被调用一次。我需要多次调用示例中未显示的其他函数
init()
只是一个例子。谢谢你的回答,因为对象在JavaScript中是通过引用传递的。我的假设是正确的,我可以使用构造函数。@Megajin好吧,没有像
这样的事情可以这样做
,它总是取决于你想要实现的事情,尝试使用构造函数,然后使用方法,然后你得到你的签名,写代码