JS装饰器 Decorator

装饰器Decorator

参考: 阮一峰 ES6

装饰器是一种函数,写成 @函数名 它可以放在类和类方法的定义前面。与Java的注解一样,都是用于增强类的方法的。

类的装饰

@AddAge
class Person {
  
}
//这里的target就是类Person,参数只能有一个
function AddAge(target) {
  console.log(target);//[Function: Person]
  target.age=10;
}
//需要使用@ts-ignore不然无法通过预编译,即使装饰器是在编译时生效的
//@ts-ignore
console.log(Person.age);//10

装饰器就是一个对类进行处理的函数。装饰器函数的第一个参数,就是所要装饰的目标类。
如果需要添加参数,可以在外面包一层函数,如下:

@AddName('张三')
class Person2{

}
function AddName(userName){
  return function(target){
    target.userName = userName;
  }
}
//@ts-ignore
console.log(Person2.userName);//张三

给类传入一个方法

function log() {
  console.log("日志输出...");
}
@addFunc([log])
class Person3 {}
function addFunc(funcs) {
  return function (target) {
    for (const func of funcs) {
      target.prototype[func.name] = func;
    }
  };
}
const p3 = new Person3();
//@ts-ignore
p3.log(); // 日志输出...

方法的装饰

class User {
  @readonly
  getName() {
    return "张三";
  }
}
/**
 *
 * @param target 类本身
 * @param name 装饰的属性(方法)名称
 * @param descriptor 属性(方法)的描述对象
 * @returns
 */
function readonly(target, name, descriptor) {
  console.log(target); //User {}
  console.log(name); //getName
  /**
   * {
   *  value: [Function: getName],
   *  writable: true,
   *  enumerable: false,
   *  configurable: true
   * }
   */
  console.log(descriptor);
  //使属性只读
  descriptor.writable = false;
  return descriptor;
}

获取类中方法名

//获取类中方法名
function GetMethodsName(target, name, descriptor) {
  if (!target.methods) {
    target.methods = [];
  }
  target.methods.push(name);
  return descriptor;
}
const u2 = new User2();
//@ts-ignore
console.log(u2.methods);//[ 'getName', 'setName' ]

在方法执行前后做一些操作

class User3 {
  @log
  test(args) {
    console.log("测试...",args);
  }
}
function log(target, name, descriptor) {
  const oldFunc = descriptor.value;
  descriptor.value = function () {
    console.log("方法执行前...", arguments);
    oldFunc.apply(this, arguments);
    console.log("方法执行后...", arguments);
  };
}
const u3 =new User3();
/**
 * 方法执行前... [Arguments] { '0': 1 }
 * 测试... 1
 * 方法执行后... [Arguments] { '0': 1 }
 */
u3.test(1);

你可能感兴趣的:(JS装饰器 Decorator)