装饰器语法

配置

babel安装

yarn add @babel/cli @babel/core @babel/preset-env -D

Babel官方的三个包,作用如下:

  • @babel/cli是Babel命令行转码工具,使用命令行进行Babel转码就需要安装它。

  • @babel/core核心包,@babel/cli依赖@babel/core。

  • @babel/preset-env这个npm包提供了ES6转换ES5的语法转换规则,需要在Babel配置文件里指定使用它。如果不使用的话,也可以完成转码,但转码后的代码仍然是ES6的,相当于没有转码。

babel装饰器插件安装

yarn add @babel/plugin-proposal-decorators -D  

配置文件

// .babelrc
{
  "presets": ["@babel/env"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}

命令

转码

npx babel index.js -o bundle.js

监听

npx babel index.js --watch --out-file bundle.js

装饰器

装饰器(Decorator)是一种与类(class)相关的语法,是一种函数,写成@函数名。它可以放在类和类方法的定义前面。

类装饰器

装饰器可以用来装饰整个类。

@log('hello')
class MyClass { }

function log(message) {
  return function(target) {
    // prototype上添加一个logger方法
    target.prototype.logger = () => `${message}${target.name} 被调用`;
  }
}

const test = new MyClass()
test.logger(); // hello,MyClass 被调用

装饰器是一个对类进行处理的函数。装饰器函数的第一个参数,就是所要装饰的目标类。装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。

类成员装饰器

类成员装饰器应用于类中的单个成员。这些成员可以是属性、方法、getter或setter,装饰器函数接受 3 个输入参数:

  • target - 成员所在的类。
  • name - 类成员的名称。
  • descriptor - 成员描述符。

只读

// 只读
class Person {
  constructor() {}

  @readonly;
  say() {
    console.log("hello world");
  }
}

function readonly(target, name, descriptor) {
  // 修改属性描述符为不可写
  descriptor.writable = false;
}

const person = new Person();

// Uncaught TypeError: Cannot assign to read only property 'say' of object '#<Person>'
person.say = function () {
  console.log("test");
}

埋点分析

// 埋点分析
class AD {
  @log("show")
  show() {
    console.log("ad is show");
  }

  @log("click")
  click() {
    console.log("ad is click");
  }
}

function log(type) {
  return function(target, name, descriptor) {
    const origin = descriptor.value;
    if (typeof origin === "function") {
      // 装饰后的方法
      descriptor.value = (...args) => {
        // 执行原函数
        origin.apply(target, args);
        // 装饰操作
        console.log(type);
      };
    }
  };
}

const ad = new AD();
ad.show();
// ad is show 
// show
ad.click();
// ad is click
// click

TS装饰器补充

参考新版 TS 装饰器:阮一峰 TypeScript 装饰器,这是在2022年通过成为标准的。但是在此之前,TypeScript 早在2014年就支持装饰器,不过使用的是旧语法。装饰器的旧语法与标准语法,有相当大的差异。旧语法以后会被淘汰,但是目前大量现有项目依然在使用它。

参考

阮一峰-装饰器
阮一峰 TypeScript 装饰器

> cd ..