javascript中装饰器是什么_如何增强函数呢

装饰器本质是接收目标函数并返回新函数的高阶函数;它不修改原函数,而通过包裹逻辑实现调用前后增强,需用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

类方法装饰器需注意 this 绑定失效

给类方法加装饰器时,若直接在类定义里写 @logDecorator(启用实验性语法),运行时该方法常会丢失 this,因为装饰器返回的新函数未自动绑定实例。解决方式只有两种:

  • 在构造函数中手动绑定:this.method = logDecorator(this.method).bind(this)
  • 改用箭头函数定义方法(但会失去原型继承优势)
  • 更推荐:装饰器内部用 return function(...args) { ... }.bind(this) 显式绑定(但需确保装饰器能访问到实例上下文)

多数真实项目中,直接用 logDecorator(target[key]) 手动包装方法比依赖 @ 语法更可控。

TypeScript 中开启装饰器要配两个开关

如果用 TypeScript,必须同时设置以下两项才能让 @ 语法被识别且生成有效代码:

  • "experimentalDecorators": true(允许语法解析)
  • "emitDecoratorMetadata": true(生成元数据,仅当需要反射时才必需)

但要注意:即使配置正确,TS 编译后仍只是把 @decorator 转成类似 __decorate([decorator], ...) 的辅助调用,底层还是靠你写的装饰器函数执行。没有那个函数,@ 就是无效标记。

真正起作用的永远是你定义的那个接收 targetpropertyKeydescriptor 的函数,而不是 @ 符号本身。