什么是JavaScript中的装饰器?

来源:我的博客作者:冷风头衔:草根站长
导读:本期聚焦于小伙伴创作的《什么是JavaScript中的装饰器?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《什么是JavaScript中的装饰器?》有用,将其分享出去将是对创作者最好的鼓励。

装饰器是JavaScript中一种用于在不修改原有代码结构的前提下,为类、类的方法、属性等添加额外功能的设计模式实现,它本质上是一个函数,通过特殊的语法糖形式作用于目标对象,在编译或运行时对目标进行包装或增强。

什么是JavaScript中的装饰器?

装饰器的基本语法

装饰器使用@符号作为前缀,紧跟在要修饰的目标之前。根据修饰的目标不同,装饰器的参数和返回值也有不同的要求。目前装饰器还处于ECMAScript的提案阶段,部分环境需要开启对应配置才能使用,比如TypeScript中需要开启experimentalDecorators配置,Babel中需要安装对应的装饰器插件。

类装饰器

类装饰器应用于类本身,接收一个参数即被装饰的类构造函数,可以修改类的构造函数或者为类添加静态属性、原型方法等。

// 定义一个简单的类装饰器,为类添加一个静态属性
function addStaticProp(target) {
  target.version = "1.0.0";
  return target;
}

// 使用装饰器修饰类
@addStaticProp
class User {
  constructor(name) {
    this.name = name;
  }
}

console.log(User.version); // 输出 1.0.0

方法装饰器

方法装饰器应用于类的原型方法,接收三个参数:目标类的原型对象、方法名、方法描述符。可以通过修改描述符来改变方法的行为,比如添加日志、权限校验等功能。

// 定义一个方法装饰器,打印方法执行前后的日志
function log(target, methodName, descriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args) {
    console.log(`方法 ${methodName} 开始执行,参数:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`方法 ${methodName} 执行结束,结果:`, result);
    return result;
  };
  return descriptor;
}

class Calculator {
  @log
  add(a, b) {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(1, 2);
// 输出:
// 方法 add 开始执行,参数: [1, 2]
// 方法 add 执行结束,结果: 3

属性装饰器

属性装饰器应用于类的属性,接收两个参数:目标类的原型对象、属性名,通常用来修改属性的描述符,比如设置属性是否可枚举、是否可写等。

// 定义一个属性装饰器,设置属性为只读
function readonly(target, propertyName) {
  Object.defineProperty(target, propertyName, {
    writable: false
  });
}

class Person {
  @readonly
  name = "张三";
}

const person = new Person();
person.name = "李四"; // 严格模式下会报错,非严格模式下赋值无效
console.log(person.name); // 输出 张三

装饰器的常见使用场景

  • 日志记录:为方法添加执行日志,无需在每个方法内部重复编写日志代码,提升代码复用性。
  • 权限校验:在接口方法前添加权限校验装饰器,判断用户是否有权限执行该操作,统一处理权限逻辑。
  • 缓存处理:为计算类方法添加缓存装饰器,相同参数调用时直接返回缓存结果,减少重复计算。
  • 参数校验:为方法参数添加校验规则,在方法执行前校验参数合法性,不合法则直接抛出错误。

装饰器的实现原理

装饰器的本质是一个高阶函数,它接收目标对象作为参数,对目标对象进行处理后返回新的对象或者直接修改原对象。以方法装饰器为例,它的执行逻辑可以近似理解为下面的普通函数调用形式:

// 普通函数形式实现方法装饰逻辑
function log(target, methodName, descriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args) {
    console.log(`方法 ${methodName} 开始执行`);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class Demo {
  sayHello() {
    console.log("Hello");
  }
}

// 手动应用装饰逻辑,等价于 @log 语法
const descriptor = Object.getOwnPropertyDescriptor(Demo.prototype, "sayHello");
const newDescriptor = log(Demo.prototype, "sayHello", descriptor);
Object.defineProperty(Demo.prototype, "sayHello", newDescriptor);

const demo = new Demo();
demo.sayHello();
// 输出:方法 sayHello 开始执行
// 输出:Hello

使用装饰器的注意事项

  • 装饰器的执行顺序是从下往上、从内到外,多个装饰器作用于同一个目标时,先执行离目标最近的装饰器。
  • 目前原生JavaScript环境对装饰器的支持还不完善,实际项目中使用通常需要借助TypeScript或者Babel等工具进行转译。
  • 装饰器只能用于类、类的方法和类的属性,不能用于普通函数,因为普通函数存在变量提升问题,装饰器无法正确绑定目标。
  • 不要在装饰器中执行过于复杂的逻辑,避免影响代码的执行性能和可读性。
装饰器是一种非常灵活的代码增强方式,合理使用可以减少重复代码,让业务逻辑更加清晰,但是也需要根据项目实际情况选择是否使用,避免过度设计。

JavaScript装饰器decoratorES6修改时间:2026-06-16 04:30:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。