从类静态方法调用ES6类构造函数

时间:2018-04-15 20:30:59

标签: javascript constructor ecmascript-6 singleton es6-class

我试图在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。我无法在代码中发现错误 - 非常感谢帮助。

3 个答案:

答案 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;