1分钟了解js装饰器

发布于 2022年 04月 02日 05:35

Js装饰器

名称解释

装饰器:在不改变类的结构的情况下对类的成员进行增强 许多面向对象的语言都有装饰器(Decorator,js主要参考了py的装饰器)函数,用来修改类的行为。目前装饰器模式仍处于第 2 阶段提案中,使用它之前需要使用 babel 模块 transform-decorators-legacy 编译成 ES5 或 ES6。

基本用法

export function decorator() {
  return function (target, key, descriptor) {
   
  }
}

@decorator()
class MyDecorator {
  constructor(){}
}

用@符号标明是一个装饰器可以接受参数,装饰器返回一个函数,函数有3个参数

target:装饰的目标对象

key:装饰的属性名

descriptor:装饰器描述

 @methodDecorator()
  toString(){}
  
  
  export function methodDecorator() {
  return function (target, key, descriptor) {
    console.log(arguments)
  }
}

类的装饰器

在类的装饰器里只返回一个参数target就是这个类本身,没有key和descriptor这两个属性 实例:装饰器添加单例模式


export function singleton() {
  return function (target) {
    target.create=function (...arg) {
      if(!target.instance){
        target.instance=new target(...arg)
      }
      return target.instance
    }
  }
}

@singleton()
class MyDecorator {
  constructor(){}
}

let a=MyDecorator.create();
let b=MyDecorator.create();
console.log(a===b)?

有了这个装饰器你就可以很方便把你的类变成一个可以创建单例对象的类。还有更多的姿势等着你们挖掘。

类方法的装饰器 在类方法的装饰器里所有属性都存在,可以通过改变descriptor.value来增强这个方法 实例:检测一个方法的运行时间

export function funTimes() {
  return function (target, key, descriptor) {
    let methods=descriptor.value;
    descriptor.value=async function (...arg) {
      console.time('test')
      await methods.apply(target.prototype,...arg)
      console.timeEnd('test')
    }
  }
}
let sleep=function (ms) {
  return new Promise((resolve)=>{
    setTimeout(()=>{
      resolve()
    },ms)
  })

}

 @funTimes()
  async test(){
  
    await sleep(5000);
  }

运行的结果会有 test: 5027.6240234375ms这样的时间戳,我们通过改变装饰器内容把这个方法成功扩展了在执行前后添加了一些非常有趣的事情,这就好像java里面的aop编程,通过这种方法我们可以不改变结构的方式完成诸如日志和事物之类的环绕编程。

静态属性的装饰器

和方法类似通过修改描述可以增强这个属性

实例:

 @readOnly(12)
  static name
  
  export function readOnly(value) {
  return function (target, key, descriptor) {
    descriptor.configurable=false;
    descriptor.writable=false
    descriptor.initializer=function(){
      return value
    }
  }
}

当你对这个name属性赋值的时候发抛出一个错误。

由于es6属性必须写在构造函数里面无法对属性进行修饰这应该是es6类设计的缺陷

推荐文章