javascript - 在TS中为长类定义动态装饰器而无需重新定义所有方法的方法

标签 javascript typescript oop es6-class

我有一个类,里面有很多方法。我们在这里不关注这个类可能会被重构并重写为几个类,因为它最终会被重构,但不知道。我想要一个装饰器,它只装饰这个类的一种方法。我们可以通过多种方式做到这一点。

类接口(interface):

interface IFoo {
    method1 (): number;
    method2 (a: string): number;
    method3 (b: IFoo): number;
    method4 (c: string | (() => string)): number;
    method5 (d: number, e: string): number;
}
  1. 经典的 OOP 解决方案:定义重新定义特定方法的装饰器,并为所有其他方法调用 super 实现。像这样的东西。

    class FooDecorator implements IFoo {
        constructor (
            private readonly provider: IFoo
        ) {}
    
        public method1 (): number {
            return this.provider.method1() + 1;
        }
    
        public method2 (a: string): number {
            return this.provider.method2.apply(this.provider, arguments);
        }
    
        public method3 (b: IFoo): number {
            return this.provider.method3.apply(this.provider, arguments);
        }
    
        public method4 (c: string | (() => string)): number {
            return this.provider.method4.apply(this.provider, arguments);
        }
    
        public method5 (d: number, e: string): number {
            return this.provider.method5.apply(this.provider, arguments);
        }
    }
    

    如您所见,写得很长并且代码重复。

  2. 尝试利用一些 JS 功能。

    interface IFooDecorator {
        method1: IFoo["method1"];
    }
    
    class FooDecorator implements IFooDecorator {
        constructor (
            private readonly provider: IFoo
        ) {
            Object.setPrototypeOf(this, provider);
        }
    
        public method1 (): number {
            return this.provider.method1() + 1;
        }
    }
    

    明显的缺点是错误的类型化和 setPrototypeOf 的使用

我也尝试过使用代理,但对使用代理的打字支持也很差。还有其他解决方案吗?第一种方法很好,以防我们可以通过 .apply 调用自动重新定义非修饰方法。

最佳答案

将装饰器实现为工厂函数,使用 Object.create 而不是 class 语法,这样您就不需要使用 Object.setPrototypeOf:

function fooDecorator<T>(provider: IFoo): T implements IFoo {
    return Object.create(provider, {
        method1: {
            value(): number {
                return provider.method1() + 1;
            },
            writable: true,
            configurable: true
        }
    });
}

关于javascript - 在TS中为长类定义动态装饰器而无需重新定义所有方法的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54218497/

相关文章:

python - 在循环或 if 语句中实例化类在编程上是否正确?

javascript - 使用 jQuery 填充隐藏文本输入

javascript - 转换 yyyy-mm-dd hh :mm:ss format to time ago

javascript - 使用JavaScript在HTML5中多次加载音频

javascript - 转换为 map 对象

javascript - Angular2 - 获取 DOM 中的特定元素并更改其类

JavaScript - 尝试使用鼠标滚轮调整图像大小

javascript - 重新连接私有(private) Typescript 类方法

python - 只能从 python 中的类后代访问的方法

java - 每次我有一个应该只有 1 个实例的类时,我是否应该使用单例?