装饰器模式的核心思想是通过包装原有对象或函数,在不改变其原有逻辑的基础上扩展新功能,这种模式在JavaScript开发中应用十分广泛,能够有效避免修改原有代码带来的风险,同时让功能扩展更加灵活。

装饰器模式的核心概念
装饰器模式属于结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。在JS中,装饰器可以作用于函数、类、类的方法等,核心是通过一层包装层来拦截原有逻辑,在原有逻辑执行前后插入自定义操作。
装饰器模式的主要优势在于遵循开闭原则,即对扩展开放,对修改关闭,当需要新增功能时不需要修改原有代码,只需要新增装饰器即可,降低了代码的耦合度。
JS实现装饰器的常见方式
1. 函数包装实现装饰器
函数包装是最基础的装饰器实现方式,通过将原函数作为参数传入装饰器函数,在装饰器内部返回一个新的函数,新的函数会先执行扩展逻辑,再执行原函数逻辑,或者反过来。
下面是一个给函数添加执行时间统计功能的装饰器示例:
// 原函数:模拟一个耗时操作
function originalFunc() {
console.log('执行原函数的核心逻辑');
// 模拟耗时
for (let i = 0; i < 1000000000; i++) {}
}
// 装饰器函数:统计函数执行时间
function timeDecorator(fn) {
return function(...args) {
const startTime = Date.now();
console.log('函数开始执行');
// 执行原函数,保留原函数的this指向和参数
const result = fn.apply(this, args);
const endTime = Date.now();
console.log(`函数执行耗时:${endTime - startTime}ms`);
return result;
};
}
// 使用装饰器包装原函数
const decoratedFunc = timeDecorator(originalFunc);
// 执行装饰后的函数
decoratedFunc();
2. ES7标准装饰器语法
ES7引入了装饰器的语法提案,目前虽然还未正式成为标准,但可以通过Babel等工具进行转译使用。ES7装饰器可以直接作用于类、类的方法、类的属性,使用@装饰器名称的语法来使用。
下面是一个类方法装饰器的示例,实现方法调用前的权限校验功能:
// 定义权限校验装饰器
function authDecorator(target, propertyKey, descriptor) {
const originalMethod = descriptor.value;
// 修改方法的描述符,替换原有方法
descriptor.value = function(...args) {
// 模拟权限校验逻辑
const hasAuth = true; // 实际场景中可以从用户信息中获取
if (!hasAuth) {
throw new Error('没有操作权限');
}
console.log('权限校验通过');
// 执行原有方法
return originalMethod.apply(this, args);
};
return descriptor;
}
class UserService {
// 使用装饰器
@authDecorator
deleteUser(userId) {
console.log(`删除用户:${userId}`);
return true;
}
}
const service = new UserService();
service.deleteUser(123);
装饰器模式的常见应用场景
日志记录
在方法执行前后自动记录日志,不需要在每个方法内部手动写日志代码,通过装饰器统一处理,减少重复代码。
性能统计
如前面示例所示,统计函数的执行时间、调用次数等性能指标,不需要侵入原有业务逻辑。
缓存处理
对于计算成本高的函数,可以通过装饰器添加缓存逻辑,当传入相同参数时直接返回缓存结果,避免重复计算。
下面是一个缓存装饰器的示例:
// 缓存装饰器
function cacheDecorator(fn) {
const cache = new Map();
return function(...args) {
// 将参数转为字符串作为缓存键
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('命中缓存,直接返回结果');
return cache.get(key);
}
// 没有缓存则执行原函数并缓存结果
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// 模拟一个耗时的计算函数
function calculate(num) {
console.log('执行计算逻辑');
return num * 2;
}
const cachedCalculate = cacheDecorator(calculate);
console.log(cachedCalculate(5)); // 第一次执行,会走计算逻辑
console.log(cachedCalculate(5)); // 第二次执行,命中缓存
使用装饰器的注意事项
首先,装饰器的执行顺序需要注意,多个装饰器作用于同一个目标时,会从外到内进入,从内到外执行。其次,使用ES7装饰器时需要确认项目的转译配置,确保装饰器语法能够被正确解析。另外,装饰器虽然灵活,但也不要过度使用,过多的装饰器嵌套会增加代码的阅读难度,不利于后续维护。
装饰器模式是JS中非常实用的设计模式,掌握它的实现方式和应用场景,能够帮助我们写出更优雅、更易维护的代码,在需要动态扩展功能的时候优先考虑装饰器模式,可以有效降低代码的耦合度。
装饰器模式JS装饰器JavaScript设计模式函数装饰器修改时间:2026-06-19 16:03:43