理解 TypeScript 装饰器。
JavaScript 是一门非常棒的编程语言。而 TypeScript 在弥补 JavaScript 的不足方面做得非常出色。它不仅添加了类型系统,还实现了一些 JavaScript 中尚不具备的额外功能,其中之一就是装饰器。
什么是装饰师?
装饰器在编程语言中由来已久。虽然定义各不相同,但简而言之,装饰器是 JavaScript 中的一种模式,用于包装某些代码以改变其行为。
在 JavaScript 和 TypeScript 中,这都是一项实验性功能。在 JavaScript 中,它目前仍处于第二阶段提案阶段,只能通过 Babel 等转译器使用。
我决定解释一下 TypeScript 装饰器,因为 TypeScript 已经将其标准化,而且两者本质上是一样的。
使用装饰器
这是一个非常简单的装饰器使用示例:
const myDecorator = (thing: Function) => {
// return something
}
@myDecorator
class Thing {
}
首先,我们定义一个函数myDecorator,然后Thing用装饰器“装饰”一个变量(在本例中是我们的类)。装饰器几乎可以返回任何东西,但大多数情况下,它用于设置类的属性等等。以下是一个实际示例:
const defaultGun = (gun: Function) => class extends gun {
ammo = 10
}
@defaultGun
class Gun {
}
现在,它将默认Gun具有一个属性。ammo
const gun = new Gun()
console.log(gun.ammo) // => 10
装饰函数
我们还可以在类方法中使用装饰器。这次,装饰器需要三个参数。
const myDecorator = (parent: Function, prop: string, descriptor: PropertyDescriptor) => {
// return something
}
class Gun {
@myDecorator
fire() {
console.log('Firing in 3... 2... 1... 🔫')
}
}
第一个参数包含被装饰对象所在的类(在本例中Gun)。第二个参数是被装饰属性的名称(在本例中fire)。最后一个参数是属性描述符,它是以下代码的输出:Object.getOwnPropertyDescriptor(parent[prop])
特性
你也可以装饰属性。它与函数装饰器非常相似,只是没有第三个参数:
const myDecorator = (parent: Function, prop: string) => {
// return something
}
更多可以装饰的地方
你还可以装饰更多地方。请查阅文档了解更多信息。
用例
装饰器有很多用途。我们在这里介绍其中的一些。
计算性能
class Gun {
@time
fire() {
console.log('Firing in 3... 2... 1... 🔫')
}
}
time可能是一个计算执行时间的函数。
装饰工厂
装饰器也可以是工厂函数,它会返回一个实际的装饰器函数。当你希望装饰器接受参数时,这非常有用。
// The decorator factory
const change = value => {
// The factory will return a new handler
return (target, prop) => {
// We replace the old value with a new one
Object.defineProperty(target, prop, {value})
}
}
然后,在进行“装饰”时,我们只需要像装饰函数一样进行装饰即可:
class Gun {
@change(20)
ammo = 10
}
const gun = new Gun();
console.log(gun.ammo) // => 20
一个实际例子:错误处理
让我们运用所学知识来解决一个现实世界的问题。
class Gun {
ammo = 0
fireTwice() {
console.log('Firing in 3... 2... 1... 🔫')
}
}
要发射两次子弹,至少需要两发子弹。我们可以使用装饰器来检查这一点:
const minAmmo = (ammo: number) => (
target: Object,
prop: string,
descriptor: PropertyDescriptor
) => {
const original = descriptor.value;
descriptor.value = function (...args) {
if (this.ammo >= ammo) original.apply(this);
else console.log('Not enough ammo!');
}
return descriptor;
}
minAmmo是一个工厂装饰器,它接受一个参数ammo,即所需的最小弹药量。
我们可以在Gun类中实现它。
class Gun {
ammo = 0
@minAmmo(2)
fireTwice() {
console.log('Firing in 3... 2... 1... 🔫')
}
}
现在如果你跑fireTwice(),它不会开火,因为我们没有足够的弹药。
好处在于我们可以直接复用这段代码,而无需重写 if 语句。假设我们需要一个fireOnce方法,我们也可以轻松地实现它。
class Gun {
ammo = 0
@minAmmo(2)
fireTwice() {
console.log('Firing twice in 3... 2... 1... 🔫')
}
@minAmmo(1)
fireOnce() {
console.log('Firing once in 3... 2... 1... 🔫')
}
}
这种装饰器在身份验证、授权以及其他各种功能上都非常有用。
喜欢这篇文章吗?❤️ 点赞。爱不释手吗?🦄 点赞。
如果你想让更多人了解这件事,请在推特上分享。
文章来源:https://dev.to/siddharthshyniben/understanding-typescript-decorators-3ifc