JavaScript Decorator on Class constructor

我是研究僧i 提交于 2020-02-04 04:14:28

问题


I'm trying to add some properties in class instances (like a Plugin system). For that, I followed this example to do that with a Class Decorator:

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();

But it doesn't work: as target is a class, I get this error:

return original.apply(this, args);
                       ^
TypeError: Class constructor AClass cannot be invoked without 'new'

I understand that I cannot do that because of Class constructor (not prototype function "constructor").

So I tried to adapt this code to:

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();

With that, bInstance is not an instance of BClass anymore. So it doesn't work also. So I get this error:

bInstance.bar();
          ^
TypeError: bInstance.bar is not a function

Any suggestion?

Thanks.


回答1:


In case somebody would still need this. Inside the decorator instead of creating the wrapper via function, you can create it with a new class wrapper:

function testDecorator(target:any) {

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


来源:https://stackoverflow.com/questions/41220382/javascript-decorator-on-class-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!