装饰器本质是接收目标函数并返回新函数的高阶函数;它不修改原函数,而通过包裹逻辑实现调用前后增强,需用fn.apply(this, args)保证this和参数透传。
JavaScript 中的装饰器(Decorator)目前仍是 Stage 3 提案,尚未进入正式标准,所以不能直接在原生环境(如浏览器控制台或 Node.js 默认模式)中使用 @ 语法。所谓“装饰器增强函数”,实际是通过一个接收目标函数、返回新函数的高阶函数来实现逻辑注入——它不修改原函数,而是在调用前后插入额外行为。
绕过编译工具(如 Babel、TypeScript)也能立即生效的方式,就是手动写一个装饰器函数。常见需求如日志、防抖、权限校验,都可以这样封装:
function logDecorator(fn) {
return function(...args) {
console.log(`[log] 调用 ${fn.name},参数:`, args);
const result = fn.apply(this, args);
console.log(`[log] 返回值:`, result);
return result;
};
}
function add(a, b) {
return a + b;
}
const loggedAdd = logDecorator(add);
loggedAdd(2, 3); // 输出日志 + 返回 5
logDecorator 接收函数 fn,返回一个新函数,该函数内部调用 fn 并包裹逻辑fn.apply(this, args) 保证 this 和参数透传,否则上下文会丢失fn.prototype 或用 bind 简化,那会破坏原函数的 this 绑定和参数长度(fn.length)给类方法加装饰器时,若直接在类定义里写 @logDecorator(启用实验性语法),运行时该方法常会丢失 this,因为装饰器返回的新函数未自动绑定实例。解决方式只有两种:
this.method = logDecorator(this.method).bind(this)
return function(...args) { ... }.bind(this) 显式绑定(但需确保装饰器能访问到实例上下文)多数真实项目中,直接用 logDecorator(target[key]) 手动包装方法比依赖 @ 语法更可控。

如果用 TypeScript,必须同时设置以下两项才能让 @ 语法被识别且生成有效代码:
"experimentalDecorators": true(允许语法解析)"emitDecoratorMetadata": true(生成元数据,仅当需要反射时才必需)但要注意:即使配置正确,TS 编译后仍只是把 @decorator 转成类似 __decorate([decorator], ...) 的辅助调用,底层还是靠你写的装饰器函数执行。没有那个函数,@ 就是无效标记。
真正起作用的永远是你定义的那个接收 target、propertyKey、descriptor 的函数,而不是 @ 符号本身。