ES6学习笔记(30)之 Decorator

2019-09-30  本文已影响0人  苦苦修行

参考:ECMAScript 6 入门

Decorator还没有定案

什么是装饰器?

举例:

@frozen class Foo {
  @configurable(false)
  @enumerable(true)
  method() {}

  @throttle(500)
  expensiveMethod() {}
}

解释:
位置:@frozen用在类本身,@configurable(false) @enumerable(true) @throttle(500)用在类方法。
目的:增加或修改类的功能。

装饰器什么时候起作用?

装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。

类装饰器

@testable
class MyTestableClass {
  // ...
}
MyTestableClass.isTestable // true

// 这就是装饰器的实现,target代码目标类,它本质是一个函数
function testable(target) {
  target.isTestable = true;
}

基本上,装饰器的行为就是下面这样:

function decorator(target){
    target.hasDecorator = true;
}

@decorator
class A {}

// 等同于

class A {}
A = decorator(A) || A; 

分析最后一段代码:很显然,decorator(A)没有返回值,或decorator(A)返回值为undefined,根据||运算的特点,首先会运行decorator(A),于是操作了target,然后发现返回undefined,于是使用||后面的A进行赋值,又因为在decorator(A)A就是target,所以A = decorator(A) || A就等到了最新的A

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

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

@testable(false)
class MyClass {}
MyClass.isTestable // false

方法装饰器

与类装饰器大同小异,主要看实现

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

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

// 以下是装饰器是如何执行的
// class的方法都是绑定到类的原型对象上的,所以target是Person.prototype

readonly(Person.prototype, 'name', descriptor);
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);

如果有多个 Decorator 如何执行,顺序是怎样的?

function dec(id){
  console.log('evaluated', id);
  return (target, property, descriptor) => console.log('executed', id);
}

class Example {
    @dec(1)
    @dec(2)
    method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

上面代码中,外层装饰器@dec(1)先进入,但是内层装饰器@dec(2)先执行。

Proxy 与 Decorator 的异同

proxy 和 decorator 都可以改变行为,不同的是,proxy 是通过一个中间件对象实现的,原对象没有改变;而decorator是直接改变原对象。

Mixin 与 Trait 模式是 Decorator 的编排方式,在此不再详解

上一篇下一篇

猜你喜欢

热点阅读