我试图在JS ES6类中实现单例模式。这是我到目前为止写的:
let instance;
export class TestClass{
constructor(){
if(new.target){
throw new Error(`Can't create instance of singleton class with new keyword. Use getInstance() static method instead`);
}
}
testMethod(){
console.log('test');
}
static getInstance(){
if(!instance) {
instance = TestClass.constructor();
}
return instance;
}
}
然而,当我调用静态方法TestClass.getInstance()
时,我没有得到类对象的实例,我得到了
ƒ anonymous() {
}
功能,无需访问testMethod。我无法在代码中发现错误 - 非常感谢帮助。
答案 0 :(得分:3)
TestClass
是构造函数。 TestClass.constructor
是内置Function
,在调用时会构造一个新的空函数(您正在记录的内容)。
TestClass
构造函数也可以TestClass.prototype.constructor
访问,这就是你的意思:
static getInstance(){
if (!instance) {
instance = TestClass.prototype.constructor();
}
return instance;
}
这当然会抛出一个异常,你不能在没有class
的情况下调用new
构造函数。
您还应简化为new TestClass
。或者甚至更好,如果你想支持子类化,new this
- 请注意静态方法中的this
是指类(构造函数)本身。
我正在尝试在JS ES6类中实现单例模式
请不要。单身人士是不好的做法。如果你的班级没有任何州,而且只有一个实例,don't use a class
。只需写下
export function testMethod() {
console.log('test');
}
// Yes, that's the whole file!
如果你坚持懒惰地构建模块,我会建议
let instance;
/*default*/ export function getInstance() {
return instance || (instance = { // use a simple object literal
testMethod(){
console.log('test');
}
});
}
那就是说,如果你坚持做一个“私人”构造函数,我会传递一个令牌:
const internal = Symbol("creation token for TestClass");
export class TestClass {
constructor(token) {
if(token !== internal) {
throw new Error("Please use the TestClass.getInstance() static method instead");
}
}
…
static getInstance(){
return new TestClass(internal); // make sure not to call `this`, otherwise subclassing could leak the token
}
}
但你永远不应该真的需要它。
答案 1 :(得分:1)
问题在于ES6 Class constructors cannot be invoked without 'new'
- 您的new.target
测试是多余的。如果您想保留Class语法,可以执行以下操作,以确保只有您的模块能够创建类:
let instance;
let creating = false;
class TestClass{
constructor(key) {
if(!creating) {
throw new Error(`Can't create instance of singleton class with new keyword. Use getInstance() static method instead`);
}
}
testMethod() {
console.log('test');
}
static getInstance() {
if(!instance) {
creating = true;
instance = new TestClass();
creating = false;
}
return instance;
}
}
const theInst = TestClass.getInstance();
theInst.testMethod();

答案 2 :(得分:0)
您尚未创建TestClass的实例,您刚刚将instance
变量指定为TestClass
的构造函数。
如果我需要,我通常会创建像这样的单身人士:
class TestClass {
constructor() {
}
testMethod() {
}
}
const instance = new TestClass();
export default instance;