我正在玩阶段2装饰器提案,我发现了一些类装饰器的问题。在遗留装饰器中,下一个示例有效,因为类装饰器将目标构造函数作为其唯一参数,但在阶段2提案中接收对象描述符。
function log(Class) {
return (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
};
}
@log
class Bar {
constructor(name, age) { }
}我读过tc39的提案-装饰器和内置装饰器,但它对我帮助不大。如何使此示例与新的提案装饰器一起工作?巴别塔可以使用内置的装饰器吗?
为了尝试一些东西,我开发了自己的基本包装装饰器,它对方法的工作与预期一样,我想将它的功能扩展到类。
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;有了这个基本的装饰器,我就可以创建一个可以工作的记录器方法装饰器。
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;
}
}发布于 2020-07-06 04:49:05
你的问题有点老了,但我认为它仍然是实际的,所以这是我的答案:
TLDR:在使用非遗留的阶段2装饰器时,使用finisher属性来包装您的类。
阶段2 API没有完整的文档记录,并且缺少一些东西和用例。
为了实现你想要的,在你的装饰器中返回的对象上定义一个特殊的finisher属性。
因此,此legacy stage-1装饰器代码:
function log(Class) {
return (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
};
}
@log
class Bar {
constructor(name, age) { }
}将等同于这个non-legacy stage-2装饰器代码:
function log(descriptor) {
return {
...descriptor,
finisher: (Class) => (...args) => {
console.log(`Arguments: ${args}`);
return new Class(...args);
},
};
}
@log
class Bar {
constructor(name, age) {}
}您可以将相同的原则应用于您的wrap函数。
https://stackoverflow.com/questions/55307753
复制相似问题