类构造函数上的JavaScript装饰器

类构造函数上的JavaScript装饰器,javascript,class,typescript,decorator,ecmascript-next,Javascript,Class,Typescript,Decorator,Ecmascript Next,我试图在类实例中添加一些属性(比如插件系统)。 为此,我使用一个类装饰器遵循以下步骤: function testDecorator(target:any) { // save a reference to the original constructor var original = target; // the new constructor behaviour var f : any = function (...args: any[]) {

我试图在类实例中添加一些属性(比如插件系统)。 为此,我使用一个类装饰器遵循以下步骤:

function testDecorator(target:any) {
    // save a reference to the original constructor
    var original = target;

    // the new constructor behaviour
    var f : any = function (...args: any[]) {
        console.log("New: " + original.name); 
        return original.apply(this, args)
    }

    // copy prototype so intanceof operator still works
    f.prototype = original.prototype;

    // return new constructor (will override original)
    return f;
}

class AbstractClass {
    constructor() {
        console.log('Init AbstractClass');
    }
}

@testDecorator
class AClass extends AbstractClass {

    constructor() {
        super();
        console.log('Init AClass');
    }

    foo() {
        console.log('Launch foo');
    }

}

class BClass extends AClass {
    constructor() {
        super();
        console.log('Init BClass');
    }

    bar() {
        console.log('Launch bar');
    }
}

var bInstance = new BClass();

bInstance.foo();
bInstance.bar();
但它不起作用:因为target是一个类,所以我得到以下错误:

return original.apply(this, args);
                       ^
TypeError: Class constructor AClass cannot be invoked without 'new'
bInstance.bar();
          ^
TypeError: bInstance.bar is not a function
我知道我不能这样做,因为类构造函数(不是原型函数“构造函数”)

因此,我尝试将此代码改编为:

function testDecorator(target:any) {
    // save a reference to the original constructor
    var original = target;

    // the new constructor behaviour
    var f : any = function (...args: any[]) {
        console.log("New: " + original.name); 
        return new original(...args)
    }

    // copy prototype so instanceof operator still works
    f.prototype = original.prototype;

    // return new constructor (will override original)
    return f;
}

class AbstractClass {
    constructor() {
        console.log('Init AbstractClass');
    }
}

@testDecorator
class AClass extends AbstractClass {

    constructor() {
        super();
        console.log('Init AClass');
    }

    foo() {
        console.log('Launch foo');
    }

}

class BClass extends AClass {
    constructor() {
        super();
        console.log('Init BClass');
    }

    bar() {
        console.log('Launch bar');
    }
}

var bInstance = new BClass();

bInstance.foo();

console.log(bInstance instanceof AClass);// true
console.log(bInstance instanceof BClass);// false

bInstance.bar();
因此,BinInstance不再是BClass的实例。所以它也不起作用。所以我得到了这个错误:

return original.apply(this, args);
                       ^
TypeError: Class constructor AClass cannot be invoked without 'new'
bInstance.bar();
          ^
TypeError: bInstance.bar is not a function
有什么建议吗


谢谢。

以防有人还需要这个。在装饰器内部,您可以使用新的类包装器创建包装器,而不是通过函数创建包装器:

function testDecorator(target:any) {

    return class extends target {
        constructor (...args) {
            console.log(`New: ${target.name}`);
            super(...args);
        }
    }
}