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