Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.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 在NodeJS中导出非单例类的正确方法是什么?_Javascript_Node.js_Ecmascript 6 - Fatal编程技术网

Javascript 在NodeJS中导出非单例类的正确方法是什么?

Javascript 在NodeJS中导出非单例类的正确方法是什么?,javascript,node.js,ecmascript-6,Javascript,Node.js,Ecmascript 6,我最近了解到,所有节点模块都是缓存的,在大多数情况下,它们的行为类似于单例 我试图解决的问题是,不能返回同一实例中的每个导入结果。这可能很容易理解,但是由于我是Node和ES6的新手,我很难找到一个可靠的设计模式 我努力实现的目标是: 私人领域 导入模块的使用者可以创建新实例 比较实例 我能想到的最好的办法是: export default () => { let _foo = 'bar'; return new class { get foo() {

我最近了解到,所有节点模块都是缓存的,在大多数情况下,它们的行为类似于单例

我试图解决的问题是,不能返回同一实例中的每个导入结果。这可能很容易理解,但是由于我是Node和ES6的新手,我很难找到一个可靠的设计模式

我努力实现的目标是:

  • 私人领域
  • 导入模块的使用者可以创建新实例
  • 比较实例
我能想到的最好的办法是:

export default () => {
   let _foo = 'bar';

   return new class {
      get foo() {
         return _foo;
      }

      set foo(value) {
         _foo = value;
      }
   };
};
const _sFoo = Symbol();

export default class {
   constructor() {
      this[_sFoo] = 'default';
   }

   get foo() {
      return this[_sFoo];
   }

   set foo(value) {
      this[_sFoo] = value;
   }
}
然而,这并没有完全达到我想要达到的所有目标

使用此方法导入模块不能使用instanceof来比较原型

导入程序在创建实例时是否使用new关键字也无关紧要。调用
let instance=new Module()
let instance=Module()
会产生相同的结果

我试图通过从函数返回中删除new关键字来解决这个问题,但是这导致导入程序必须执行以下操作才能获得新实例:
new(Module())

我也尝试过导出构造函数,但这导致了私有字段的丢失

从节点模块导出构造函数函数/类的正确方法是什么?

更新:

在玩了更多的游戏后,我得出了以下结论:

export default () => {
   let _foo = 'bar';

   return new class {
      get foo() {
         return _foo;
      }

      set foo(value) {
         _foo = value;
      }
   };
};
const _sFoo = Symbol();

export default class {
   constructor() {
      this[_sFoo] = 'default';
   }

   get foo() {
      return this[_sFoo];
   }

   set foo(value) {
      this[_sFoo] = value;
   }
}
这似乎满足了我的所有目标,但我仍然不确定这是否是最好的设计模式

我试图解决的问题是,不能返回同一实例中的每个导入结果。这可能很容易理解,但是由于我是Node和ES6的新手,我很难找到一个可靠的设计模式

您有两个选择:

  • 您可以导出构造函数,并让加载模块的代码调用该构造函数来创建自己的对象。这允许调用代码创建所需数量的独立对象。导出构造函数需要调用方使用
    new
    ,除非构造函数明确检测到它们在没有
    new
    的情况下被调用,然后进行调整以仍然返回新实例

  • 您可以导出一个factory函数,并让加载模块的代码调用该factory函数来创建任意数量的自己的对象。工厂函数将作为普通函数调用,并且每次调用时都会返回一个新对象

  • 您可以导出一个方法,该方法在被调用时执行任何您想要的操作,包括创建所需的对象并返回它(可能还嵌入到其他对象中)。这只是工厂函数的一个变体,但可能同时包含一系列内容

  • 我努力实现的目标是:

    私人领域

    对于每个对象的私有字段,上述内容根本没有帮助。这是一个完全不同的讨论

    导入模块的使用者可以创建新实例

    上面的选项1允许调用者直接使用
    new
    。其他选项是出厂功能,因此它们不会使用
    new

    比较实例

    您必须直接导出构造函数(上面的选项1)才能使用
    instanceof
    。其他选项不导出构造函数,因此您没有任何要使用的
    instanceof

    从节点模块导出构造函数函数/类的正确方法是什么


    您只需导出构造函数。在Javascript中,构造函数只是函数,因此您只需导出构造函数,然后调用方就可以使用
    let x=new SomeConstructor()
    创建自己的对象。他们同样可以使用
    if(SomeConstructor的x实例)
    。使用ES6语法,只需导出类名,这相当于导出构造函数。

    我个人认为构造函数是唯一的选项,除非1。你不是在做OO(顺便说一句,这很好),只是把对象当作名称空间或2。构造函数接受的参数太多,因此最好使用builder@jfriend00谢谢你的意见。我最终选择了构造函数路线。您的私有成员变量方案可以通过
    Object.getOwnPropertySymbols(obj)
    从外部看到。没有一个ES6定义的方法来处理真正的私有成员。我知道获得真正隐私的唯一方法仍然是:。这里有很多讨论:这就像导出一个类一样简单,我不知道为什么还要讨论这个问题。我建议亲吻并遵循
    \u-foo
    命名惯例。拥有“真正私有”的符号道具会使调试和测试变得复杂,而且没有任何帮助。@estus我现在意识到,这就像导出一个类一样简单。我所担心的是,在类定义之外定义的字段在多个实例之间共享。我仍然纠结于是否使用命名约定或符号来定义“私有”字段。我开始更倾向于使用命名约定,因为字段并不是真正私有的。当符号出现时,我尝试过这种模式,但很糟糕。您很难在漂亮的产品代码中看到它。是的,当您需要从外部访问“私有”字段时,“私有”字段就成了一个陷阱——用于测试、扩展等等前缀和不可枚举描述符就足够了。在99%的情况下,我只是在普通属性前面加上
    来表示私有属性,并且更多地依赖于约定而不是实际的隐私。我有时使用
    Object.defineProperty()
    创建它,使其不可枚举。只有几次,我觉得自己有理由费心打造一个真正的私有财产。