加入收藏 | 设为首页 | 会员中心 | 我要投稿 厦门网 (https://www.xiamenwang.cn/)- 数据采集、建站、AI开发硬件、专属主机、云硬盘!
当前位置: 首页 > 教程 > 正文

es6修饰器的用处是什么

发布时间:2023-07-28 08:54:04 所属栏目:教程 来源:转载
导读:   这篇文章主要讲解了“es6修饰器的作用是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“es6修饰器的作用是什
  这篇文章主要讲解了“es6修饰器的作用是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“es6修饰器的作用是什么”吧!
 
  在es6中,修饰器用来注释或修改类和类的方法,依赖于ES5的“Object.defineProperty”方法,写法为“@函数名”;修饰器其实就是一个函数,通常放在类和类方法的前面。修饰器可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
 
  修饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
 
  这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
 
  ES6 装饰器(修饰器)
 
  在 ES6 中,装饰器(Decorator)是一种与类相关的语法,用来注释或修改类和类方法。
 
  装饰器其实就是一个函数,通常放在类和类方法的前面。
 
  @decorateClass
 
  class Example {
 
      @decorateMethods
 
      method(){}
 
  }
 
  在上面的代码中使用了两个装饰器,其中 @decorateClass() 装饰器用在类本身,用于增加或修改类的功能;@decorateMethods() 装饰器用在类的方法,用于注释或修改类方法。
 
  两种类型装饰器(修饰器)
 
  装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
 
  装饰器只能用于类和类的方法,下面我们分别看下两种类型的装饰器的使用
 
  类装饰器
 
  类装饰器用来装饰整个类
 
  类装饰器的参数
 
  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 {}
 
  类方法装饰器
 
  类方法装饰器用来装饰类的方法
 
  类方法装饰器的参数
 
  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);
 

(编辑:厦门网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章