装饰器是JavaScript中用于类和方法的元编程工具,通过@expression语法在运行时修改行为或添加元数据。1. 类装饰器接收构造函数,可用于日志记录或标记可注入服务,如@Injectable为类定义元数据。2. 方法装饰器接收目标对象、成员名和描述符,可实现只读控制或性能监控,如@time测量执行时间。3. 使用Reflect.defineMetadata和Reflect.getMetadata可在装饰器中存储和读取元数据,常用于路由定义等场景。4. 装饰器目前处于Stage 3,需借助Babel或TypeScript支持,适合构建框架级功能如依赖注入、序列化和路由系统。

JavaScript 装饰器为开发者提供了在类和方法上添加元数据、修改行为的能力,是元编程的重要工具。虽然目前装饰器仍处于提案阶段(Stage 3),但通过 Babel 或 TypeScript 已可实际使用。本文带你掌握装饰器在类与方法上的元数据编程实践。
装饰器基础概念
装饰器是一种特殊类型的声明,可以被附加到类声明、方法、访问器、属性或参数上。它使用 @expression 形式,其中 expression 求值后必须是一个函数,该函数会在运行时被调用,传入被装饰的声明信息。
装饰器函数接收不同的参数,取决于它应用的位置:
- 类装饰器:接收构造函数作为唯一参数
- 方法装饰器:接收目标对象、成员名和属性描述符
- 参数装饰器:接收目标对象、成员名和参数索引
类装饰器与元数据注入
类装饰器可用于记录类型信息、注册服务或添加静态元数据。例如,定义一个 @logClass 装饰器来标记类并输出其创建日志:
立即学习“Java免费学习笔记(深入)”;
function logClass(target: Function) {console.log('类已创建:', target.name);
}
@logClass
class UserService { }
// 输出: 类已创建: UserService
更进一步,可以使用装饰器为类附加自定义元数据,比如用于依赖注入系统的标识:
function Injectable(target: Function) {Reflect.defineMetadata('injectable', true, target);
}
@Injectable
class ApiService { }
// 检查元数据
const isInjectable = Reflect.getMetadata('injectable', ApiService);
console.log(isInjectable); // true
方法装饰器与行为拦截
方法装饰器可用于日志记录、权限检查、性能监控等场景。它能访问属性描述符,因此可以修改方法的行为。
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。它不是新的编程语言,而是一种使用现有标准的新方法,最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容,不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。《php中级教程之ajax技术》带你快速
例如,实现一个 @readonly 装饰器防止方法被重写:
function readonly(target: any, name: string, descriptor: PropertyDescriptor) {descriptor.writable = false;
}
或使用 @time 记录方法执行耗时:
function time(target: any, name: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.time(name);
const result = originalMethod.apply(this, args);
console.timeEnd(name);
return result;
};
}
class DataProcessor {
@time
process() {
// 模拟耗时操作
for (let i = 0; i }
}
结合 Reflect Metadata 使用
要高效管理元数据,推荐使用 reflect-metadata 库。它扩展了 JavaScript 的反射能力,允许你在任意对象上存储和读取类型化元数据。
安装并引入:
npm install reflect-metadata然后可以在装饰器中设置和读取元数据:
import 'reflect-metadata';function Route(path: string) {
return (target: any, key: string, desc: PropertyDescriptor) => {
Reflect.defineMetadata('route', path, target, key);
};
}
class Controller {
@Route('/users')
getAll() { }
}
// 读取路由信息
const routePath = Reflect.getMetadata('route', Controller.prototype, 'getAll');
console.log(routePath); // '/users'
基本上就这些。装饰器配合元数据 API,让 JavaScript 具备了类似 Java 注解的能力,适合构建框架级功能如路由、依赖注入、序列化等。只要注意环境支持和编译配置,就能安全使用。









