【问题标题】:JavaScript Decorator on Class constructor类构造函数上的 JavaScript 装饰器
【发布时间】:2017-05-04 08:59:16
【问题描述】:

我正在尝试在类实例中添加一些属性(例如插件系统)。 为此,我按照example 使用类装饰器来做到这一点:

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

但它不起作用:因为目标是一个类,我得到这个错误:

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

我知道我不能这样做,因为类构造函数(不是原型函数“构造函数”)。

所以我尝试将这段代码修改为:

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

这样,bInstance 就不再是 BClass 的实例了。所以它也不起作用。所以我得到这个错误:

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

有什么建议吗?

谢谢。

【问题讨论】:

    标签: javascript class typescript decorator ecmascript-next


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-04-09
      • 2019-10-06
      • 1970-01-01
      • 2014-04-18
      • 2017-09-14
      • 2021-02-04
      • 2020-08-20
      • 2016-05-08
      • 2011-06-06
      相关资源
      最近更新 更多