什么是装饰器

装饰器以其最简单的形式只是将一段代码与另一段代码包装在一起的一种方式-实际上就是“修饰”它。 您可能以前已经听说过这个概念,即::功能组合::或::高阶函数::。

装饰器是对类、函数、属性之类的一种装饰,可以针对其添加一些额外的行为。

对于装饰器,可以简单地理解为是非侵入式的行为修改,也就是可以认为就是在原有代码外层包装了一层处理逻辑。

生活中的列子

个人认为装饰器是一种解决方案,而并非是狭义的@Decorator,后者仅仅是一个语法糖罢了。

装饰器在身边的例子随处可见,一个简单的例子,水龙头上边的起泡器就是一个装饰器,在装上以后就会把空气混入水流中,掺杂很多泡泡在水里。 但是起泡器安装与否对水龙头本身并没有什么影响,即使拆掉起泡器,也会照样工作,水龙头的作用在于阀门的控制,至于水中掺不掺杂气泡则不是水龙头需要关心的。

Javascript中的装饰器

DecoratorES7 的一个新语法,正如其“装饰器”的叫法所表达的,他通过添加 @方法名 可以对一些对象进行装饰包装然后返回一个被包装过的对象,可以装饰的对象包括:::类,属性,方法::等。

注意:在使用它之前需要引入babel模块 transform-decorators-legacy 编译成 ES5 或 ES6。

ES6中的类

class Cat {
  say() {
    console.log(“meow~”)
  }
}

上面这段代码是 ES6 中定义类的写法,其实是一个语法糖,而实际上我们给一个类添加一个属性的时候,会调用到 Object.defineProperty 方法,它接收3个参数:targetnamedescriptor,所以上面的代码实际上在执行时是这样的:

function Cat() {}
Object.defineProperty(Cat.prototype, “say”, {
  value: function() { console.log(“meow~”) },
  enumerable: false,
  configurable: true,
  writable: true
});

好了,了解了类是怎么工作的以后,我们再来看看装饰器在JS中到底是怎么工作的吧

作用于类的装饰器

当装饰的对象是类时,我们操作的就是这个类本身,即装饰器函数的第一个参数,就是要装饰的目标类

@decorator
class A {}

// 等同于
class A {}
A = decorator(A) || A

举个例子:一个日志装饰器

@log
class MyClass {}

function log(target) { // 这个 target 在这里就是 MyClass 这个类
  target.prototype.logger = () => `${target.name} 被调用`
}

const myClass = new MyClass()
myClass.logger() // MyClass 被调用