0

0

理解 TypeScript 中的装饰器:第一原理方法

心靈之曲

心靈之曲

发布时间:2024-09-21 09:48:10

|

1185人浏览过

|

来源于dev.to

转载

理解 typescript 中的装饰器:第一原理方法

typescript 中的装饰器提供了一种强大的机制来修改类、方法、属性和参数的行为。虽然它们看起来像是一种现代的便利,但装饰器植根于面向对象编程中成熟的装饰器模式。通过抽象日志记录、验证或访问控制等常见功能,装饰器允许开发人员编写更清晰、更易于维护的代码。

在本文中,我们将从首要原则探索装饰器,分解其核心功能,并从头开始实现它们。在此过程中,我们将了解一些实际应用程序,这些应用程序展示了装饰器在日常 typescript 开发中的实用性。

什么是装饰器?

在 typescript 中,装饰器只是一个可以附加到类、方法、属性或参数的函数。此函数在设计时执行,使您能够在代码运行之前更改代码的行为或结构。装饰器支持元编程,允许我们在不修改原始逻辑的情况下添加额外的功能。

让我们从一个方法装饰器的简单示例开始,该示例记录调用方法的时间:

function log(target: any, propertykey: string, descriptor: propertydescriptor) {
  const originalmethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`calling ${propertykey} with arguments: ${args}`);
    return originalmethod.apply(this, args);
  };

  return descriptor;
}

class example {
  @log
  greet(name: string) {
    return `hello, ${name}`;
  }
}

const example = new example();
example.greet('john');

这里,日志装饰器包装了greet方法,在执行之前记录其调用和参数。此模式对于将日志记录等横切关注点与核心逻辑分离非常有用。

装饰器如何工作

typescript 中的装饰器是接受与其所装饰的项目相关的元数据的函数。基于这些元数据(如类原型、方法名称或属性描述符),装饰器可以修改行为甚至替换被装饰的对象。

装饰器的类型

装饰器可以应用于各种目标,每个目标都有不同的目的:

  • 类装饰器:接收类构造函数的函数。
function classdecorator(constructor: function) {
  // modify or extend the class constructor or prototype
}
  • 方法装饰器:接收目标对象、方法名称和方法描述符的函数。
function methoddecorator(target: any, propertykey: string, descriptor: propertydescriptor) {
  // modify the method's descriptor
}
  • 属性装饰器:接收目标对象和属性名称的函数。
function propertydecorator(target: any, propertykey: string) {
  // modify the behavior of the property
}
  • 参数装饰器:接收目标、方法名称和参数索引的函数。
function parameterdecorator(target: any, propertykey: string, parameterindex: number) {
  // modify or inspect the method's parameter
}

将参数传递给装饰器

装饰器最强大的功能之一是它们接受参数的能力,允许您自定义它们的行为。例如,让我们创建一个方法装饰器,它根据参数有条件地记录方法调用。

function logconditionally(shouldlog: boolean) {
  return function (target: any, propertykey: string, descriptor: propertydescriptor) {
    const originalmethod = descriptor.value;

    descriptor.value = function (...args: any[]) {
      if (shouldlog) {
        console.log(`calling ${propertykey} with arguments: ${args}`);
      }
      return originalmethod.apply(this, args);
    };

    return descriptor;
  };
}

class example {
  @logconditionally(true)
  greet(name: string) {
    return `hello, ${name}`;
  }
}

const example = new example();
example.greet('typescript developer');

通过将 true 传递给 logconditionally 装饰器,我们确保该方法记录其执行情况。如果我们传递 false,则跳过日志记录。这种灵活性是使装饰器具有多功能性和可重用性的关键。

装饰器的实际应用

装饰器在许多库和框架中都有实际用途。以下是一些值得注意的示例,说明了装饰器如何简化复杂的功能:

海霆企业网站系统(HT-EWCMS)1.1
海霆企业网站系统(HT-EWCMS)1.1

HT-EWCMS 为 Hetty - Enterprise Web Content Management System 的英文缩写,即海霆企业网站内容管理系统,HT-EWCMS为您提供一个高效快速和强大的企业网站解决方案,兼容各种主流操作系统和浏览器。HT-EWCMS著作权已在中华人民共和国国家版权局注册,海霆科技为 HT-EWCMS 产品的开发商,依法独立拥有 HT-EWCMS 产品著作权,著作

下载
  • 类验证器中的验证:在数据驱动的应用程序中,验证至关重要。 class-validator 包使用装饰器来简化验证 typescript 类中字段的过程。
import { isemail, isnotempty } from 'class-validator';

class user {
  @isnotempty()
  name: string;

  @isemail()
  email: string;
}

在此示例中,@isemail 和 @isnotempty 装饰器确保电子邮件字段是有效的电子邮件地址并且名称字段不为空。这些装饰器消除了手动验证逻辑的需要,从而节省了时间。

  • 使用 typeorm 进行对象关系映射:装饰器广泛用于 typeorm 等 orm 框架中,用于将 typescript 类映射到数据库表。此映射是使用装饰器以声明方式完成的。
import { entity, column, primarygeneratedcolumn } from 'typeorm';

@entity()
class user {
  @primarygeneratedcolumn()
  id: number;

  @column()
  name: string;

  @column()
  email: string;
}

这里,@entity、@column 和 @primarygeneeratedcolumn 定义了 user 表的结构。这些装饰器抽象了 sql 表创建的复杂性,使代码更具可读性和可维护性。

  • angular 依赖注入:在 angular 中,装饰器在管理服务和组件方面发挥着关键作用。 @injectable 装饰器将一个类标记为可以注入其他组件或服务的服务。
@injectable({
  providedin: 'root',
})
class userservice {
  constructor(private http: httpclient) {}
}

在这种情况下,@injectable 装饰器向 angular 的依赖注入系统发出信号,表明应在全局范围内提供 userservice。这允许跨应用程序无缝集成服务。

实现你自己的装饰器:分解

装饰器的核心就是函数。让我们分解一下从头开始创建装饰器的过程:

类装饰器

类装饰器接收类的构造函数,可以用来修改类原型,甚至替换构造函数。

function addtimestamp(constructor: function) {
  constructor.prototype.timestamp = new date();
}

@addtimestamp
class myclass {
  id: number;
  constructor(id: number) {
    this.id = id;
  }
}

const instance = new myclass(1);
console.log(instance.timestamp);  // outputs the current timestamp

方法装饰器

方法装饰器修改方法描述符,允许您更改方法本身的行为。

function logexecutiontime(target: any, propertykey: string, descriptor: propertydescriptor) {
  const originalmethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    const start = performance.now();
    const result = originalmethod.apply(this, args);
    const end = performance.now();
    console.log(`${propertykey} executed in ${end - start}ms`);
    return result;
  };

  return descriptor;
}

class service {
  @logexecutiontime
  execute() {
    // simulate work
    for (let i = 0; i < 1e6; i++) {}
  }
}

const service = new service();
service.execute();  // logs the execution time

物业装修师

属性装饰器允许您拦截属性访问和修改,这对于跟踪更改非常有用。

function trackChanges(target: any, propertyKey: string) {
  let value = target[propertyKey];

  const getter = () => value;
  const setter = (newValue: any) => {
    console.log(`${propertyKey} changed from ${value} to ${newValue}`);
    value = newValue;
  };

  Object.defineProperty(target, propertyKey, {
    get: getter,
    set: setter,
  });
}

class Product {
  @trackChanges
  price: number;

  constructor(price: number) {
    this.price = price;
  }
}

const product = new Product(100);
product.price = 200;  // Logs the change

结论

typescript 中的装饰器允许您以干净、声明的方式抽象和重用功能。无论您使用验证、orm 还是依赖注入,装饰器都有助于减少样板文件并保持代码模块化和可维护性。从第一原理出发了解它们的工作原理可以更轻松地充分利用它们的潜力并根据您的应用程序定制解决方案。

通过更深入地了解装饰器的结构和实际应用,您现在已经了解了它们如何简化复杂的编码任务并简化各个领域的代码。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

686

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

324

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1137

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

359

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

737

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

577

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

420

2024.04.29

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

25

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号