【发布时间】:2023-01-04 05:00:19
【问题描述】:
我的任务是实现一个只允许执行一次装饰方法的方法装饰器。
例如:
class Test {
data: any;
@once
setData(newData: any) {
this.newData = newData;
}
}
const test = new Test();
test.setData([1,2,3]);
console.log(test.data); // [1,2,3]
test.setData('new string');
console.log(test.data); // [1,2,3]
我尝试了很多组合来使一个被调用两次的函数什么都不做,但这不是我应该拥有的,单元测试失败了,所以,这就是我到目前为止所拥有的:
const once = (
target: Object,
propertyKey: string | symbol,
descriptor: PropertyDescriptor
) => {
const method = descriptor.value;
descriptor.value = function (...args){
// ???
}
};
单元测试:
describe('once', () => {
it('should call method once with single argument', () => {
class Test {
data: string;
@once
setData(newData: string) {
this.data = newData;
}
}
const test = new Test();
test.setData('first string');
test.setData('second string');
assert.strictEqual(test.data, 'first string')
});
it('should call method once with multiple arguments', () => {
class Test {
user: {name: string, age: number};
@once
setUser(name: string, age: number) {
this.user = {name, age};
}
}
const test = new Test();
test.setUser('John',22);
test.setUser('Bill',34);
assert.deepStrictEqual(test.user, {name: 'John', age: 22})
});
it('should return always return first execution result', () => {
class Test {
@once
sayHello(name: string) {
return `Hello ${name}!`;
}
}
const test = new Test();
test.sayHello('John');
test.sayHello('Mark');
assert.strictEqual(test.sayHello('new name'), 'Hello John!')
})
});
请问你能帮帮我吗?提前致谢!
【问题讨论】:
-
很好的问题——我在一两周前遇到了同样的问题,并且在放弃之前玩了很久。我并不经常需要那个功能,所以我手动实现了这个概念:在类
this._setData = false上声明一个属性。在setData里面,只运行代码if (!this._setData),在运行代码的最后,做一个this._setData = true。这意味着代码只会运行一次。至于将其推广到装饰器以应用于任何方法(而不是每次都必须手动声明this._value),我也想知道! -
是的,我想我可以采用这种方法,但问题是设置数据函数只是一个例子,我不知道后面可以调用哪些函数或类似的东西。正如你在单元测试中看到的那样,有setData函数,下面是setUser,装饰器应该在任何地方都有相同的行为,但我不知道该怎么做:(
-
在
setData中,你可能是指this.data = newData
标签: javascript typescript