Heim  >  Artikel  >  Web-Frontend  >  Was ist ein Dekorateur in es6?

Was ist ein Dekorateur in es6?

青灯夜游
青灯夜游Original
2022-03-23 13:57:123842Durchsuche

In es6 ist Decorator eine klassenbezogene Syntax, die zum Kommentieren oder Ändern von Klassen und Klassenmethoden verwendet wird. Der Decorator ist eigentlich eine Funktion, die während der Kompilierung ausgeführt wird, mit der Syntax „@Funktionsname“, die normalerweise vor der Definition von steht Klassen und Klassenmethoden. Es gibt zwei Arten von Dekoratoren: Klassendekoratoren und Klassenmethodendekoratoren.

Was ist ein Dekorateur in es6?

Die Betriebsumgebung dieses Tutorials: Windows 7-System, ECMAScript Version 6, Dell G3-Computer.

Das Decorator-Muster ermöglicht das Hinzufügen neuer Funktionen zu einem vorhandenen Objekt, ohne seine Struktur zu ändern. Bei dieser Art von Entwurfsmuster handelt es sich um ein Strukturmuster, das als Hülle um eine vorhandene Klasse fungiert.

Dieses Muster erstellt eine Dekorationsklasse, um die ursprüngliche Klasse zu umschließen und zusätzliche Funktionalität bereitzustellen, während gleichzeitig die Integrität der Klassenmethodensignatur gewahrt bleibt.

ES6 Decorator

In ES6 ist Decorator eine klassenbezogene Syntax, die zum Kommentieren oder Ändern von Klassen und Klassenmethoden verwendet wird.

Ein Dekorator ist eigentlich eine Funktion, die normalerweise vor Klassen und Klassenmethoden platziert wird.

Die Änderung des Verhaltens der Klasse durch den Dekorator erfolgt beim Kompilieren des Codes, nicht zur Laufzeit; das Wesentliche des Dekorators ist die zur Kompilierungszeit ausgeführte Funktion. Der Dekorator kann zum Dekorieren der gesamten Klasse verwendet werden

@decorateClass
class Example {
    @decorateMethods
    method(){}
}

在上面的代码中使用了两个装饰器,其中 @decorateClass() 装饰器用在类本身,用于增加或修改类的功能;@decorateMethods() 装饰器用在类的方法,用于注释或修改类方法。

两种类型装饰器

装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。

装饰器只能用于类和类的方法,下面我们分别看下两种类型的装饰器的使用

1、类装饰器

类装饰器用来装饰整个类

类装饰器的参数

target: 类本身,也相当于是 类的构造函数:Class.prototype.constructor。

@decorateClass
class Example {
    //...
}

function decorateClass(target) {
    target.isTestClass = true
}

如上面代码中,装饰器 @decorateClass 修改了 Example 整个类的行为,为 Example 类添加了静态属性 isTestClass。装饰器就是一个函数,decorateClass 函数中的参数 target 就是 Example 类本身,也相当于是类的构造函数 Example.prototype.constructor.

装饰器传参

上面实现的装饰器在使用时是不能传入参数的,如果想要在使用装饰器是传入参数,可以在装饰器外面再封装一层函数

@decorateClass(true)
class Example {
    //...
}

function decorateClass(isTestClass) {
    return function(target) {
  target.isTestClass = isTestClass
  }
}

上面代码中实现的装饰器在使用时可以传递参数,这样就可以根据不同的场景来修改装饰器的行为。

实际开发中,React 与 Redux 库结合使用时,常常需要写成下面这样。

class MyReactComponent extends React.Component {}
export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

有了装饰器,就可以改写上面的代码。

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}

2、类方法装饰器

类方法装饰器用来装饰类的方法

类方法装饰器的参数

  • target:

  • 装饰器修饰的类方法是静态方法:target 为类的构造函数

  • 装饰器修饰的类方法是实例方法:target 为类的原型对象

  • method:被修饰的类方法的名称

  • descriptor:被修饰成员的属性描述符

// descriptor对象原来的值如下
{
  value: specifiedFunction,
  enumerable: false,
  configurable: true,
  writable: true
};
class Example {
    @log
    instanceMethod() { }

    @log
    static staticMethod() { }
}

function log(target, methodName, descriptor) {
  const oldValue = descriptor.value;

  descriptor.value = function() {
    console.log(`Calling ${name} with`, arguments);
    return oldValue.apply(this, arguments);
  };

  return descriptor;
}

如上面代码中,装饰器 @log 分别装饰了实例方法 instanceMethod 和 静态方法 staticMethod。@log 装饰器的作用是在执行原始的操作之前,执行 console.log 来输出日志。

类方法装饰器传参

上面实现的装饰器在使用时是不能传入参数的,如果想要在使用装饰器是传入参数,可以在装饰器外面再封装一层函数

class Example {
    @log(1)
    instanceMethod() { }

    @log(2)
    static staticMethod() { }
}

function log(id) {
    return (target, methodName, descriptor) => {
    const oldValue = descriptor.value;

    descriptor.value = function() {
      console.log(`Calling ${name} with`, arguments, `this id is ${id}`);
      return oldValue.apply(this, arguments);
    };

    return descriptor;
  }
}

上面代码中实现的装饰器在使用时可以传递参数,这样就可以根据不同的场景来修改装饰器的行为。

类装饰器与类方法装饰器的执行顺序

如果在一个类中,同时使用装饰器修饰类和类的方法,那么装饰器的执行顺序是:先执行类方法的装饰器,再执行类装饰器。

如果同一个类或同一个类方法有多个装饰器,会像剥洋葱一样,先从外到内进入,然后由内到外执行。

// 类装饰器
function decoratorClass(id){
    console.log('decoratorClass evaluated', id);

    return (target) => {
        // target 类的构造函数
        console.log('target 类的构造函数:',target)
        console.log('decoratorClass executed', id);
    }
}
// 方法装饰器
function decoratorMethods(id){
    console.log('decoratorMethods evaluated', id);
    return (target, property, descriptor) => {
        // target 代表

        // process.nextTick((() => {
            target.abc = 123
            console.log('method target',target)
        // }))
        console.log('decoratorMethods executed', id);

    }
}

@decoratorClass(1)
@decoratorClass(2)
class Example {
    @decoratorMethods(1)
    @decoratorMethods(2)
    method(){}
}

/** 输入日志 **/
// decoratorMethods evaluated 1
// decoratorMethods evaluated 2
// method target Example { abc: 123 }
// decoratorMethods executed 2
// method target Example { abc: 123 }
// decoratorMethods executed 1
// decoratorClass evaluated 1
// decoratorClass evaluated 2
// target 类的构造函数: [Function: Example]
// decoratorClass executed 2
// target 类的构造函数: [Function: Example]
// decoratorClass executed 1

如上面代码中,会先执行类方法的装饰器 @decoratorMethods(1) 和 @decoratorMethods(2),执行完后再执行类装饰器 @decoratorClass(1) 和 @decoratorClass(2)

上面代码中的类方法装饰器中,外层装饰器 @decoratorMethods(1) 先进入,但是内层装饰器 @decoratorMethods(2) 先执行。类装饰器同理。

利用装饰器实现AOP切面编程

function log(target, name, descriptor) {
    var oldValue = descriptor.value;

    descriptor.value = function () {
        console.log(`Calling "${name}" with`, arguments);
        return oldValue.apply(null, arguments);
    }
    return descriptor;
}

// 日志应用
class Maths {
    @log
    add(a, b) {
        return a + b;
    }
}
const math = new Maths();
// passed parameters should get logged now
math.add(2, 4);

【相关推荐:javascript视频教程web前端

Das obige ist der detaillierte Inhalt vonWas ist ein Dekorateur in es6?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn