JavaScript 装饰器:增强函数和类的利器167


JavaScript 装饰器(Decorators)是一种强大的语法糖,允许你在不修改原函数或类代码的情况下,为其添加额外的功能。 它们提供了一种简洁且可读性更高的方式来扩展代码,避免了繁琐的包装器函数或继承的复杂性。虽然装饰器提案最初被标准化委员会否决,但在 ECMAScript 2022 中最终被正式引入,并被广泛支持。本文将深入探讨 JavaScript 装饰器的使用、原理以及各种应用场景。

一、 装饰器的基本语法和原理

装饰器本质上是一个函数,它接收被装饰的目标(函数或类)作为参数,并返回一个修改后的目标。 装饰器用 `@` 符号紧跟在被装饰的目标之前。 一个简单的装饰器示例如下:```javascript
function myDecorator(target) {
("装饰器执行了");
// 可以修改 target,例如添加属性或方法
= "This was added by decorator";
return target; // 返回修改后的目标
}
@myDecorator
function myFunction() {
("myFunction 执行了");
}
(); // 输出:This was added by decorator
myFunction(); // 输出:装饰器执行了 myFunction 执行了
```

在这个例子中,`myDecorator` 函数就是装饰器。它接收 `myFunction` 作为参数,并在其中添加了一个属性 `addedProperty`。 `@myDecorator` 语法将 `myDecorator` 函数应用于 `myFunction`。 注意,装饰器函数的执行时机是在定义阶段,而不是运行时。

二、 装饰器参数

装饰器可以接受参数,这使得装饰器更加灵活。 参数可以通过装饰器函数的参数列表传递。 例如:```javascript
function logDecorator(message) {
return function(target) {
(message + ": " + );
};
}
@logDecorator("函数被装饰了")
function myFunction() {}
```

在这个例子中,`logDecorator` 接收一个 `message` 参数。 它返回一个函数,这个函数才是真正的装饰器函数,接收被装饰的目标 `target`。 这种方式允许你根据不同的参数来定制装饰器的行为。

三、 类装饰器

装饰器不仅可以用于函数,还可以用于类。 类装饰器接收类的构造函数作为参数。 例如:```javascript
function classDecorator(target) {
= function() {
("这是一个被装饰的方法");
};
return target;
}
@classDecorator
class MyClass {
constructor() {}
}
let myInstance = new MyClass();
(); // 输出:这是一个被装饰的方法
```

在这个例子中,`classDecorator` 向 `MyClass` 的原型链添加了一个新的方法 `decoratedMethod`。

四、 方法装饰器

方法装饰器用来装饰类的具体方法。它接收三个参数: target (目标类)、name (方法名)、descriptor (方法描述符)。```javascript
function methodDecorator(target, name, descriptor) {
(`装饰方法 ${name}`);
const originalMethod = ;
= function(...args) {
("方法执行前");
const result = (this, args);
("方法执行后");
return result;
};
return descriptor;
}
class MyClass {
@methodDecorator
myMethod(a, b) {
return a + b;
}
}
const myInstance = new MyClass();
((1, 2)); // 输出: 装饰方法 myMethod 方法执行前 方法执行后 3
```

方法装饰器可以修改方法的行为,例如添加日志、权限控制等。

五、 属性装饰器

属性装饰器可以用来修改类的属性,它接收三个参数:target (目标类), name (属性名), descriptor (属性描述符)。```javascript
function propertyDecorator(target, name, descriptor) {
(`装饰属性 ${name}`);
= false; //设置为不可写
return descriptor;
}
class MyClass {
@propertyDecorator
name = "初始值";
}
const myInstance = new MyClass();
(); // 初始值
= "新值"; //不会改变值
(); // 初始值
```

六、 装饰器组合

可以将多个装饰器应用于同一个目标,装饰器将按照声明的顺序执行。```javascript
function decorator1(target) {
("decorator1 执行");
}
function decorator2(target) {
("decorator2 执行");
}
@decorator1
@decorator2
class MyClass {}
// 输出:decorator2 执行 decorator1 执行
```

七、 装饰器的应用场景

装饰器在各种场景下都非常有用,例如:
日志记录: 在函数或方法执行前后记录日志。
权限控制: 检查用户是否有权限执行某个方法。
缓存: 缓存函数或方法的返回值。
AOP (面向切面编程): 在不修改原代码的情况下添加横切关注点,例如事务管理、异常处理。
依赖注入: 将依赖项注入到类或函数中。

八、 总结

JavaScript 装饰器是一种强大的工具,可以帮助我们编写更简洁、更可维护的代码。 通过理解装饰器的基本语法和原理,以及各种应用场景,我们可以充分利用装饰器来提高代码质量和开发效率。 虽然装饰器的使用需要一定的学习成本,但其带来的好处是显而易见的。 随着 JavaScript 标准化的不断完善,装饰器必将发挥更大的作用。

2025-06-24


下一篇:JavaScript 中 Range 对象的深入解读与应用