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

Fur*_*man 5 javascript singleton constructor ecmascript-6 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我调用静态方法时TestClass.getInstance(),我没有得到类对象的实例,我得到了

ƒ anonymous() {

}
Run Code Online (Sandbox Code Playgroud)

函数,无需访问 testMethod。我在我的代码中找不到错误 - 将不胜感激。

Ber*_*rgi 5

TestClass是构造函数。TestClass.constructor是 builtin Function,它在调用时构造一个新的空函数(您正在记录的内容)。

TestClass构造也可以作为访问的TestClass.prototype.constructor,这就是你可能是指:

static getInstance(){
    if (!instance) {
        instance = TestClass.prototype.constructor();
    }
    return instance;
}
Run Code Online (Sandbox Code Playgroud)

这当然会抛出一个异常,如果class没有new.

您还应该简化为new TestClass. 或者甚至更好,如果您想支持子类化,请new this注意this在静态方法中是指类(构造函数)本身。

我正在尝试在 JS ES6 类中实现单例模式

请不要。单身人士是不好的做法。如果您的类没有任何状态,并且无论如何只有一个实例,请不要使用class. 写就好了

export function testMethod() {
    console.log('test');
}
// Yes, that's the whole file!
Run Code Online (Sandbox Code Playgroud)

如果你坚持懒惰地构建模块,我会推荐

let instance;
/*default*/ export function getInstance() {
    return instance || (instance = { // use a simple object literal
        testMethod(){
            console.log('test');
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

也就是说,如果你坚持要创建一个“私有”构造函数,我会传递一个令牌:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

但你永远不应该真正需要它。