Falando sobre decoradores de texto datilografado de java annotations-annotations and decorators

Eu compilei os " Princípios básicos das anotações Java (anotações) " antes. Em Java, as anotações são óleo e sal. Para JavaScript, também é um tempero oriental na Europa medieval.

Decoradores e anotações

Decoradores e anotações não conseguiram descobrir seus conceitos específicos antes. Acho que todos são baseados em metaprogramação. As anotações são uma espécie de modo de decoração.

  • Anotação (anotação) : só fornecem suporte metadados adicionais , e não pode conseguir qualquer coisa . Um Scanner adicional é necessário para executar as operações correspondentes com base em metadados.

  • Decorator (o Decorator) : é fornecido apenas para a definição de sequestro , as classes podem, nos métodos de classe de referência, classe de atributo de classe e método a ser modificado . Nenhum suporte de metadados é fornecido.

A conexão entre anotações e decoradores:

Adicione metadados por meio de anotações e, em seguida, obtenha esses metadados no decorador, conclua a modificação da classe, métodos de classe, etc., você pode adicionar suporte a metadados no decorador, por exemplo, você pode usar a função de fábrica do decorador e o decorador Adicione suporte de metadados à função.

A diferença entre anotações e decoradores

Embora a sintaxe seja muito semelhante, diferentes conceitos podem ser usados ​​em diferentes linguagens:

  • Linguagens que usam anotação : AtScript, Java, C # (chamado de Atributo).

  • Linguagens usando Decorator : Python, JavaScript / ECMAScript.

Conceitualmente, podemos ver claramente que anotações e decoradores não têm semântica em comum!

Anotações e decoradores podem simular uns aos outros e não são equivalentes. O decorador pode ser executado naturalmente no tempo de execução e a anotação deve ser refletida (o tipo em si não está disponível)

O modo de herança é uma maneira importante de enriquecer a "conotação" de subelementos, seja herdando interfaces ou subclasses herdando classes básicas. O modelo decorador pode compactar os módulos existentes sem alterar a relação de herança para enriquecer a conotação sem afetar as funções originais. Comparado com a herança, é mais flexível.

Uma das características mais poderosas do decorador é sua capacidade de refletir metada (refletir metada)

Por que você precisa de reflexão em JavaScript?

A reflexão é usada para descrever o código que pode inspecionar outros códigos no mesmo sistema (ou ele mesmo).

Os aplicativos JavaScript estão ficando cada vez maiores, portanto, algumas ferramentas (como a inversão de contêineres de controle) e funções como (asserção de tipo de tempo de execução) são necessárias para gerenciar essa complexidade crescente.

Uma API de reflexão poderosa deve nos permitir inspecionar um objeto desconhecido em tempo de execução e descobrir tudo sobre ele. Devemos ser capazes de encontrar algo assim:

  1. O nome da entidade.

  2. O tipo de entidade.

  3. Quais interfaces são implementadas por entidades.

  4. O nome e o tipo do atributo da entidade.

  5. O nome e o tipo dos parâmetros do construtor da entidade

Em JavaScript, podemos usar funções como Object.getOwnPropertyDescriptor () ou Object.keys () para encontrar algumas informações sobre a entidade, mas precisamos refletir para implementar ferramentas de desenvolvimento mais poderosas.

No entanto, as coisas estão prestes a mudar, porque o TypeScript começa a suportar alguns recursos do Reflection. Mas, na verdade, são apenas algumas funções JavaScript, que podem nos ajudar a anotar o código ou modificar o comportamento do código - essa prática é geralmente chamada de metaprogramação.

Decorador TypeScript

Os decoradores podem abstrair bem o código e são mais adequados para lógica de empacotamento que pode ser reutilizada em vários lugares.

Cinco maneiras de decorar

  • Declaração de classe

  • Atributos

  • método

  • parâmetro

  • acessor

Decorador de classe

O decorador de classe permite que os desenvolvedores interceptem o construtor da classe .

Observação: quando declaramos uma classe, o decorador será chamado em vez de esperar até que a classe seja instanciada.

Quando você decora uma classe, o decorador não tem efeito nas subclasses dessa classe. Vamos congelar uma classe para evitar completamente que outros programadores se esqueçam acidentalmente desse recurso.

@Frozen
class IceCream {}

function Frozen(constructor: Function) {
  Object.freeze(constructor);
  Object.freeze(constructor.prototype);
}

console.log(Object.isFrozen(IceCream)); // true

class FroYo extends IceCream {} // 报错,类不能被扩展

当装饰函数直接修饰类的时候,装饰函数接受唯一的参数constructor,这个参数就是该被修饰类本身。

此外,在修饰类的时候,如果装饰函数有返回值,该返回值会重新定义这个类,也就是说当装饰函数有返回值时,其实是生成了一个新类,该新类通过返回值来定义。

方法装饰器 Method Decorator

方法装饰器来覆写一个方法,改变它的执行流程,以及在它执行前后额外运行一些代码

下面这个例子会在执行真正的代码之前弹出一个确认框。如果用户点击了取消,方法就会被跳过。注意,这里我们装饰了一个方法两次,这两个装饰器会从上到下地执行。

function log(target, key, descriptor) {}
class P {
    @log
    foo() {
      console.log('Do something');
    }
}

对于类的函数的装饰器函数,依次接受的参数为:

  • target:如果修饰的是类的实例函数,那么target就是类的原型。如果修饰的是类的静态函数,那么target就是类本身。

  • key: 该函数的函数名。

  • descriptor:该函数的描述属性,比如 configurable、value、enumerable等。

属性装饰器 Property Decorator

属性装饰器极其有用,因为它以监听对象状态的变化

为了充分了解接下来这个例子,建议你先熟悉一下 JavaScript 的属性描述符(PropertyDescriptor)。

function foo(target,name){}
class P{
   @foo
   name = 'Jony'
}

这里对于类的属性的装饰器函数接受两个参数,

  • 第一个参数:

    • 对于静态属性而言,是类本身

    • 对于实例属性而言,是类的原型,

  • 第二个参数:所指属性的名字

类函数参数的装饰器

类函数的参数装饰器可以修饰类的构建函数中的参数,以及类中其他普通函数中的参数。该装饰器在类的方法被调用的时候执行

function foo(target,key,index){}
class P{
   test(@foo a){
   }
}

类函数参数的装饰器函数接受三个参数

  • target: 类本身

  • key:该参数所在的函数的函数名

  • index: 该参数在函数参数列表中的索引值

装饰器可以起到分离复杂逻辑的功能,且使用上极其简单方便。与继承相比,也更加灵活,可以从装饰类,到装饰类函数的参数,可以说武装到了“牙齿”。

Typescript中的元数据操作

可以通过reflect-metadata包来实现对于元数据的操作。首先我们来看reflect-metadata的使用,首先定义使用元数据的函数:

const formatMetadataKey = Symbol("format");

function format(formatString: string) {
    return Reflect.metadata(formatMetadataKey, formatString);
}

function getFormat(target: any, propertyKey: string) {
    return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}

这里的format可以作为装饰器函数的工厂函数,因为format函数返回的是一个装饰器函数,上述的方法定义了元数据Sysmbol("format"),用Sysmbol的原因是为了防止元数据中的字段重复,而format定义了取元数据中相应字段的功能。

接着我们来在类中使用相应的元数据:

class Greeter {
    @format("Hello, %s")
    name: string;

    constructor(name: string) {
        this.name = message;
    }
    sayHello() {
        let formatString = getFormat(this, "name");
        return formatString.replace("%s", this.name);
    }
}

const g = new Greeter("Jony");
console.log(g.sayHello());

在上述中,我们在name属性的装饰器工厂函数,执行@format("Hello, %s"),返回一个装饰器函数,且该装饰器函数修饰了Greeter类的name属性,将“name”属性的值写入为"Hello, %s"。

然后再sayHello方法中,通过getFormat(this,"name")取到formatString为“Hello,%s”.


参考列表:

TypeScript中的装饰器&元数据反射:从新手到专家四 https://zhuanlan.zhihu.com/p/42220487

理解 TypeScript 装饰器 https://zhuanlan.zhihu.com/p/65764702

【认真脸】注解与装饰器的点点滴滴 https://zhuanlan.zhihu.com/p/22277764

聊聊Typescript中的设计模式——装饰器篇(decorators) https://github.com/forthealllight/blog/issues/33




转载本站文章《从java注解漫谈到typescript装饰器——注解与装饰器》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/typescript/2020_0721_8528.html


Acho que você gosta

Origin blog.51cto.com/zhoulujun/2535588
Recomendado
Clasificación