You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

被装饰的单例类instanceof判断失效问题排查

解决单例装饰器导致instanceof失效的问题

你的问题出在装饰器返回了一个与原类完全独立的包装类,而实际创建的实例是原类的实例,两者的原型链没有关联,导致instanceof校验失败。

问题根源

当你用@Singleton()装饰TestSingleton后,TestSingleton这个变量已经指向装饰器返回的包装类,而非你最初定义的TestSingleton类。但你的装饰器里是通过new constructor(...)创建原类的实例,这个实例的原型链只和原类绑定,和包装类毫无关系,所以x instanceof TestSingleton(此时TestSingleton是包装类)自然返回false。

修复方案

这里提供两种可靠的修复思路:

方案一:让包装类继承原类

通过extends让包装类继承原类,保证原型链的连续性,同时保留单例逻辑:

interface Type<T = any> extends Function {
    new (...args: any[]): T;
}

function Singleton() {
    let instance: Object;
    return function <SingletonFunction extends Type>(
        constructor: SingletonFunction
    ) {
        // 让包装类继承原类,确保原型链关联
        const WrapperClass = class extends constructor {
            constructor(...args: any[]) {
                if (instance) {
                    return instance;
                }
                // 调用原类构造函数
                super(...args);
                instance = this;
            }
        };
        // 保持类名一致,方便调试
        Object.defineProperty(WrapperClass, 'name', { value: constructor.name });
        return WrapperClass as SingletonFunction;
    };
}

方案二:重写原类的构造函数(不替换原类引用)

这种方式不会改变TestSingleton的指向,直接修改原类的构造函数实现单例,同时保留原类的所有静态成员和原型链:

interface Type<T = any> extends Function {
    new (...args: any[]): T;
}

function Singleton() {
    return function <SingletonFunction extends Type>(
        constructor: SingletonFunction
    ) {
        let instance: InstanceType<SingletonFunction>;
        // 保存原构造函数
        const originalConstructor = constructor;

        // 重写构造函数实现单例逻辑
        const singletonConstructor = function(...args: any[]) {
            if (instance) {
                return instance;
            }
            instance = new originalConstructor(...args);
            // 修正this的原型指向
            Object.setPrototypeOf(this, originalConstructor.prototype);
            return instance;
        } as unknown as SingletonFunction;

        // 同步原类的原型、类名和静态成员
        singletonConstructor.prototype = originalConstructor.prototype;
        Object.defineProperty(singletonConstructor, 'name', { value: originalConstructor.name });
        Object.assign(singletonConstructor, originalConstructor);

        return singletonConstructor;
    };
}

测试验证

用任意一种方案修改后,运行你的测试代码会得到预期结果:

const x = new TestSingleton([1, 2, 3, 4, 5, 6]);
const y = new TestSingleton([6, 7, 8, 9, 1]);

console.log(x === y); // true
console.log(x instanceof TestSingleton); // true

内容的提问来源于stack exchange,提问作者Nilesh Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:03:26