我正在研究阶段2装饰器的建议,但发现类装饰器存在一些问题。在旧版装饰器中,下一个示例可行,因为类装饰器将目标构造函数作为唯一参数,但是在阶段2提议中,它接收到对象描述符。
function log(Class) {
return (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
};
}
@log
class Bar {
constructor(name, age) { }
}
我已经阅读了tc39提案装饰器和内置装饰器,但是并没有太大帮助。如何使该示例与新的投标装饰器一起使用?可以将内置装饰器与babel一起使用吗?
为了尝试一些东西,我开发了自己的基本包装装饰器,它可以按预期的方法使用,并且我想将其功能扩展到类。
const wrap = f => {
return wrapped => {
const { kind } = wrapped;
if (kind === 'class') {
return f(wrapped);
}
const { descriptor } = wrapped;
const original = descriptor.value;
descriptor.value = f(original);
return { ...wrapped, descriptor };
};
};
export default wrap;
有了这个基本的装饰器,我就可以创建可以正常工作的logger方法装饰器。
import wrap from './wrap';
const loggerFunction = f => {
const name = f.name;
return function test(...args) {
console.log(`starting ${name} with arguments ${args.join(', ')}`);
return f.call(this, ...args);
};
};
export default wrap(loggerFunction);
我可以通过这种方式使用它:
class Foo {
@logger
method(argument) {
return argument;
}
}
答案 0 :(得分:1)
您的问题有点老了,但我认为它仍然是实际的,所以这是我的答案:
TLDR:在使用非旧版阶段2装饰器时,请使用finisher
属性包装您的类。
第2阶段的API尚未完全记录,缺少某些内容和用例。
为了实现所需的功能,请在装饰器中返回的对象上定义特殊的finisher
属性。
因此,此legacy
阶段1装饰代码:
function log(Class) {
return (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
};
}
@log
class Bar {
constructor(name, age) { }
}
等同于此non-legacy
第二阶段装饰器代码:
function log(descriptor) {
return {
...descriptor,
finisher: (Class) => (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
},
};
}
@log
class Bar {
constructor(name, age) {}
}
您可以将相同的原理应用于wrap
函数。