JS-学习ES6之- Decorator 修饰器

目录

  • 概述
  • 类的修饰
  • 方法的修饰

1、概述

用于给对象在运行期间动态的增加某个功能,职责等。相较通过继承的方式来扩充对象的功能,装饰器显得更加灵活,首先,我们可以动态给对象选定某个装饰器,而不用 hardcore 继承对象来实现某个功能点。其次:继承的方式可能会导致子类繁多,仅仅为了增加某一个单一的功能点,显得有些多余了。

所以,装饰器的作用:
- 是继承关系的一种替代
- 动态的类添加额外的功能
- 在不改变接口的前提下,增强类的性能

2、类的修饰

修饰器是一个对类进行处理的函数。用来修改类的行为。

注意,修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数。

类的修饰器函数的第一个参数 target 指向类本身。

2.1 给类增加静态属性

@testable 
class MyTestableClass {
  // ..
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable; // true

上面代码中,@testable 就是一个修饰器。它修改了 MyTestableClass 这个类的行为,为它加上了 静态属性 isTestabletestable 函数的参数 targetMyTestableClass 类本身。

如果觉得一个参数不够用,可以在修饰器外面再封装一层函数。

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable; // true

@testable(false)
class MyTestableClass {}
MyTestableClass.isTestable; // false

上面代码中,修饰器 testable 可以接受参数,这就等于可以修改修饰器的行为。

2.2 给类的实例增加属性

前面的例子是为类添加一个静态属性, 如果想添加实例属性,可以通过目标类的 prototype 对象操作。

function testable(target){
  target.prototype.isTestable = true;
}

@testable 
class MyTestableClass {
  // ...
}

let obj = new MyTestableClass();
obj.isTestable; // true

3、方法的修饰

类的方法的修饰器函数的第一个参数 target 指向类的原型对象。

这是因为类中的方法,实际上是作用于实例对象上的。

3.1 示例一

class Person {
  @readonly
  getName() { return `${this.first} ${this.last}` }
}

function readonly(target, name, descriptor) {
  // descriptor对象原来的值如下:
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // }
  descriptor.writable = false;
  return descriptor;
}

上面代码中,修饰器 readonly 用来修饰“类”的 getName 方法。
第一个参数是类的原型对象,第二个参数是所要修饰的属性名,本例中为 getName() 函数, 第三个参数为该属性的描述对象。

3.2 示例二

创建一个@log修饰器,可以起到输出日志的作用。

class Math {
  @log
  add(a, b) {
    return a + b;
  }

  function log(target, name, descriptor) {
    // 保存旧的方法add
    const oldValue = descriptor.value; 

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

    // 必须返回descriptor对象
    return descriptor;
  }
}

let math = new Math();
math.add(1, 2);

上面代码中,@log 修饰器的作用就是在执行原始的操作之前,执行一次 console.log ,从而达到输出日志的目的。

4、修饰器不能用于函数

修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。类是不会提升的,所以就没有这方面的问题。

参考资料

ES6入门-修饰器

细说ES7 JavaScript Decorators

JavaScript-装饰器函数(Decorator)

[译]探秘ES2016中的Decorators【推荐】

ES7 Decorator 装饰器 | 淘宝前端团队

简单了解一下ES6的修饰器

装饰器模式&&ES7 Decorator 装饰器

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值