如何定义和使用类装饰器、方法装饰器和属性装饰器?

推荐答案

类装饰器

类装饰器是一个函数,它接收类构造函数作为唯一参数,并可以修改或增强该类的行为。

-- -------------------- ---- -------
-------- ------------------- -
    -------------------------
    -----------------------------------
-

-------
----- ------- -
    --------- -------
    -------------------- ------- -
        ------------- - --------
    -
    ------- -
        ------ ------- - - --------------
    -
-

@sealed 装饰器会使用 Object.seal 来阻止对 Greeter 类及其原型进行修改,从而达到类不可扩展的目的。

方法装饰器

方法装饰器是一个函数,它接收三个参数:

  1. target:类的原型对象。
  2. propertyKey:方法名,字符串。
  3. descriptor:属性描述符对象。

方法装饰器可以用来修改方法的行为,例如记录方法的执行时间。

-- -------------------- ---- -------
-------- ----------- ---- ------------ ------- ----------- ------------------- -
    ----- -------------- - -----------------
    ---------------- - -------- --------- ------ -
        -------------------- -------------- ---- ------------ ------
        ----- ------ - -------------------------- ------
        ------------------- -------------- ----------- --------
        ------ -------
    --
    ------ -----------
-

----- ------- -
  ----
  ------ ------- -- ------- -
      ------ - - --
  -
-
----- ---------- - --- ----------
----------------- ---

@log 装饰器会在执行 add 方法前后打印日志。

属性装饰器

属性装饰器是一个函数,接收两个参数:

  1. target:类的原型对象。
  2. propertyKey:属性名,字符串。

属性装饰器通常用来修改属性的描述符,例如实现只读属性或者验证属性值。

-- -------------------- ---- -------
-------- ---------------- ---- ------------ -------- ---- -
  ----------------------------- ------------ -
    --------- ------
  ---
-


----- ------ -
    ---------
    ----- ------ - --------

    ------------- -
    -
-
----- ------ - --- --------
-- ----------- - ----- -- -----------
------------------------

@readonly装饰器会修改name属性的描述符,使其 writablefalse,从而成为只读属性。

本题详细解读

装饰器(Decorator)简介

装饰器是一种特殊类型的声明,可以附加到类声明、方法、访问符、属性或参数上。它们使用 @expression 这种形式,其中 expression 必须求值为一个函数,该函数会在运行时被调用,并传递被装饰的声明作为参数。 装饰器是 ES7/TypeScript 的语法,它提供了一种简洁的方式来修改类和成员的行为,实现 AOP(面向切面编程)的思想。

类装饰器详解

类装饰器接收类的构造函数作为参数。这使得我们可以在类创建时对其进行修改,或者添加额外的功能。

示例解释:

  • sealed(constructor) 函数接收类的构造函数 constructor,然后使用 Object.seal 来禁止对该类及其原型添加或删除属性。
  • @sealed 装饰器直接应用于 Greeter 类,这会在 Greeter 类创建时调用 sealed 函数,从而使其不可扩展。

用途:

  • 控制类的可扩展性(如示例中的sealed
  • 注入依赖
  • 修改类的构造函数
  • 类级别的日志记录

方法装饰器详解

方法装饰器接收类的原型对象、方法名以及该方法对应的属性描述符。属性描述符包含了方法的值(函数本身)、可写性、可枚举性以及可配置性等信息。我们可以修改这些属性,从而修改方法的行为。

示例解释:

  • log(target, propertyKey, descriptor) 函数接收类原型、方法名和属性描述符,并修改了 descriptor.value,使得在原方法执行前后打印日志。
  • @log 装饰器应用于 add 方法,当 add 方法被调用时,会先执行日志打印,然后执行原方法,最后返回结果。

用途:

  • 方法执行时间记录
  • 方法执行结果缓存
  • 权限验证
  • 方法参数校验
  • 错误处理

属性装饰器详解

属性装饰器接收类的原型对象和属性名。它允许我们修改属性的描述符,例如使其只读、添加验证逻辑等。

示例解释:

  • readonly(target, propertyKey) 函数接收类原型和属性名,并使用 Object.defineProperty 修改属性的 writable 属性为 false
  • @readonly 装饰器应用于 Person 类的 name 属性,使其成为只读属性。

用途:

  • 实现只读属性
  • 添加属性值验证逻辑
  • 实现数据绑定
  • 序列化和反序列化控制
纠错
反馈