深入理解和应用JavaScript中的装饰器

JavaScript一直在发展和吸取新的附加功能,以增强其对开发者的吸引力。其中一个新语法就是装饰器。装饰器对于开发者来说,是一枚强大的工具,它可以在忽略函数的内部巧妙地修改其行为。

什么是装饰器?

装饰器就是一个函数,它可以修改类的行为或属性,而不需要知道类内部的具体实现。装饰器用于提高代码的可读性和健壮性,同时缩减冗余的代码。

如何使用装饰器?

让我们首先查看一下如何在JS中使用装饰器。在编写装饰器时,你需要将要装饰的对象,其原始描述符和装饰器的目标传给装饰器。

例如,我们有一个讲述狗叫声的函数,我们想要装饰它:

scss 复制代码
function dogBark() {
  console.log('Woof woof');
}

dogBark();

这是一段简单的代码,但我们希望这个函数在每次调用时都打印出函数被调用的时间。这就是我们使用装饰器的地方。首先我们需要创建一个装饰器:

javascript 复制代码
function decorator(func) {
  return function () {
    console.log(`Function ${func.name} was called at: ${new Date().toLocaleTimeString()}`);
    func();
  };
}

然后我们把这个装饰器应用到我们的函数上:

ini 复制代码
dogBark = decorator(dogBark);
dogBark();

现在,每次我们调用dogBark函数时,都会打协议输出函数被调用的时间。

类装饰器

到此为止,我们已经成功地创建了一个将功能添加到单个函数的装饰器。那么如果我们想要添加到类上呢?

让我们设置一个类,并为其添加一些装饰:

typescript 复制代码
@logger
class Dog {
  constructor() {
    console.log('new dog was created');
  }
}

在这段代码中,我们使用 "@logger" 装饰器装饰了整个 "Dog" 类。那么问题来了,这个 "@logger" 装饰器是什么样的呢?这个装饰器需要注入到类的原型链中,以此来拦截类的实例。

下面,我们就来看看这个装饰器:

javascript 复制代码
function logger(target) {
  let original = target;

  function construct(constructor, args) {
    let instance = new Function('origin', 'return new origin(...args)')(original, args);
    console.log(`New dog was created at: ${new Date().toLocaleTimeString()}`);
    return instance;
  }

  let prototype = Object.create(original.prototype);
  let surrogate = function (...args) { return construct(original, args); };
  surrogate.prototype = prototype;
  return surrogate;
}

这个装饰器有点复杂,但仔细分析后你会发现,它在实例化类之后,打印出一条消息显示实例创建的时间。

属性和方法装饰器

最后,我们可以通过装饰器来修改类的属性和方法。

例如,我们有这样一个类:

javascript 复制代码
class Dog {
  bark() {
    console.log('Woof woof');
  }

  @uppercase
  breed = 'Poodle';
}

function uppercase(target, key) {
  let value = target[key];

  if (delete target[key]) {
    Object.defineProperty(target, key, {
      get: () => value,
      set: (newVal) => value = newVal.toUpperCase(),
      enumerable: true,
      configurable: true
    });
  }
}

在这份代码中,我们创建了一个装饰器将狗的品种强制大写。

结语

JS装饰器是一个强大的工具,允许我们在不修改原始函数或类的情况下增加新功能。装饰器在很多流行的JS库中都有使用,掌握装饰器也许会为你的JS生涯开辟新的可能性。

相关推荐
CharlesYu011 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
平头哥技术团队1 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰2 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面3 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方3 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结3 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言4 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒4 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机4 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生
2601_962382435 小时前
剑指大前端全栈工程师(全2册)主要情节
javascript·实战案例·全栈工程师·剑指大前端·html5+css3