JavaScript 装饰器介绍

简介: 装饰器是一种包装代码的简单方法,它也是一种设计模式,能够扩展包装代码的功能而不修改它。

image.png

装饰器是一种包装代码的简单方法,它也是一种设计模式,能够扩展包装代码的功能而不修改它。


尽管装饰器在 TypeScript 和 Python 等语言中被广泛使用,但是 JavaScript 装饰器的支持仍处于第 2 阶段提案中(stage 2 proposal)。但是,我们可以借助 Babel 和 TypeScript 编译器使用 JavaScript 装饰器。


本文将详细讨论 JavaScript 装饰器,提升理解。冲~


简介



在 JavaScript 中,装饰器有一种特殊的语法。它们以 @ 符号为前缀,放置在我们需要装饰的代码之前。另外,可以一次使用多个装饰器。


代码示例:

@readonly
class Example {
    @log()
    exampleFunction() {}
}


前面已经提到,JavaScript 装饰器支持仍处于提案阶段。但是,装饰器的概念对 JavaScript 来说并不新鲜,因为高阶函数是函数装饰器的另一种形式。

总的来说,我们可以在 JavaScript 中分出 3 种类型的装饰器:


  • 函数装饰器——用函数来包装函数。
  • 类装饰器—— 一次应用于整个类。
  • 类成员装饰器——应用于类的成员


目前,不能在浏览器或 Node.js 环境中运行类装饰器,因为它们需要转译器支持。但是,如果使用函数式装饰器,则可以在任何地方运行它们。


函数装饰器



我们可以尝试用一个函数包装另一个函数,来扩展功能而不改变原始函数。


function multiply(x, y) {
  console.log('Total : ' + (x*y));
}
function logDecorator(logger) {
  return function (message) {
    const result = logger.apply(this, arguments);
    console.log("Logged at:", new Date().toLocaleString());
    return result;
  }
}
const wrapperFunction = logDecorator(multiply);
wrapperFunction(10,10)


在上面的例子中,wrapperFunction() 通过 logDecorator() 修改了 multiply() 函数,它可以像任何 JavaScript 函数一样被调用。

image.png


自从引入了高阶函数以来,JavaScript 函数装饰器就一直存在。但是,我们不能对 JavaScript 的类使用相同的方法。


类装饰器



类装饰器有点不同。如果尝试使用相同的方法,将会报错 TypeError:

image.png

如果你对 JavaScript this 关键字理解透彻,可以克服这个问题。但这不是最简单方法。

类装饰器应用于整个类。因此,我们所做的任何修改都会影响整个类。对类装饰器所做的任何事情都需要通过返回一个新的构造函数来替换类构造函数。


举个例子:

function log(name) {
  return function decorator(Class) {
    return (...args) => {
      console.log(`Arguments for ${name}: ${args}`);
      return new Class(...args);
    };
  }
}
@log('Multiply')
class Calculator {
    constructor (x,y) { }
}  
calculator = new Calculator(10,10);
// Arguments for Multiply: [10, 10]
console.log(calculator);
// Calculator {}


log() 函数接受 Calculator 类作为参数,并返回一个新函数来替换 Calculator 类的构造函数;


类成员装饰器



类成员装饰器应用于类中的单个成员。这些成员可以是属性、方法、getter 或 setter,装饰器函数接受 3 个输入参数:


  • Target - 成员所在的类。
  • Name - 类成员的名称。
  • descriptor - 成员描述符。


代码示例:

function readonly(target, name, descriptor) {
  descriptor.writable = false;
   return descriptor;
}
class Example {
  x() {}
  @readonly
  y() {}
}
const myClass = new Example();
myClass.x = 10;
myClass.y = 20;


在 readonly() 函数中,我们将描述符的可写属性设置为 false。然后,将它用作函数 y() 的装饰器。如果尝试修改它,会得到一个 TypeError。


此外,我们还可以创建自定义装饰器,并将它们用作类成员装饰器,如下:


function log(name) {
  return function decorator(t, n, descriptor) {
    const original = descriptor.value;
    if (typeof original === 'function') {
      descriptor.value = function (...args) {
        console.log("Logged at:", new Date().toLocaleString());
        try {
          const result = original.apply(this, args);
          console.log(`Result from ${name}: ${result}`);
          return result;
        } cach (e) {
          console.log(`Error from $ {name}: ${e}`);
          thro e;
        }
      };
    }
    return descriptor;
  };
}
class Calculator {
  @log('Multiply')
    multiply(x,y){
      return x*y;
  }
}    
calculator = new Calculator();
calculator.multiply(10,10);
// Logged at: 1/12/2022, 08:00:00 PM
// Result from Multiply: 100


Calculator 类有一个名为 multiply() 的方法,并使用 log() 函数对其进行修饰。Log() 函数接受单个参数作为输入,当我们调用装饰器 (@log('Multiply')) 时,我们可以将值传递给该参数。


小结



将装饰器引入 JavaScript 的主要目的是在 JavaScript 类和类属性之间共享功能。

但是,这并不是装饰器带来的唯一优势。


装饰器允许开发人员编写干净且可重用的代码。开发人员可以使用装饰器轻松地将功能的增强与代的码特性分开。


除此之外,装饰器语法非常简单,允许在不增加代码复杂性的情况下向类和属性添加新功能。


这使得代码更易于维护和调试。

以上,便是本篇分享~~~

我是掘金安东尼,输出暴露输入,技术洞见生活,再会~


相关文章
|
缓存 JavaScript 前端开发
《现代Javascript高级教程》装饰器
JavaScript修饰器:简化代码,增强功能 引言 在JavaScript中,修饰器(Decorator)是一种特殊的语法,用于修改类、方法或属性的行为。修饰器提供了一种简洁而灵活的方式来扩展和定制代码功能。本文将详细介绍JavaScript修饰器的概念、语法和应用场景,并提供相关的代码示例。
80 0
|
JavaScript 前端开发
JavaScript 的Decorator 装饰器介绍
Angular大量使用了JS的装饰器特性,先看 ruanyifeng的介绍 使用babel转换 步骤 : npm install -g babel-cli npm init; npm install --save-dev babel-plugin-t...
1123 0
|
JavaScript 前端开发 存储
Javascript装饰器的妙用
最近新开了一个Node项目,采用TypeScript来开发,在数据库及路由管理方面用了不少的装饰器,发觉这的确是一个好东西。装饰器是一个还处于草案中的特性,目前木有直接支持该语法的环境,但是可以通过 babel 之类的进行转换为旧语法来实现效果,所以在TypeScript中,可以放心的使用@Decorator。
1394 0
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的个人健康管理系统小程序附带文章源码部署视频讲解等
8 2
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的高校宿舍信息管理系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电影交流平台小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的电器维修系统小程序附带文章源码部署视频讲解等
7 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的大学生校园兼职微信小程序附带文章源码部署视频讲解等
9 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的二手物品交易平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的二手物品交易平台附带文章源码部署视频讲解等
6 1
|
1天前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的机电公司管理信息系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的机电公司管理信息系统附带文章源码部署视频讲解等
9 0