ES7 - 装饰器@

295 阅读1分钟

注:Decorator提案经过大幅修改,目前还没有定案

阮老师

什么是装饰器

  • 装饰器在很多语言中都有,是一种和类(class)相关语法,用来注释修改类和类方法。ES7引入,目前还没有定案
  • 装饰器是一种函数,写成@ + 函数名
  • 大部分时候当作高阶函数使用

作用范围

  • 类的方法

类的装饰

@testable
class MyTestableClass {
    // ...
}

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

MyTestableClass.isTestable // true

从上面例子可以看出

  • testable函数就是一个装饰器函数,该函数接受一个参数target,就是所要装饰的目标类
  • 装饰器执行的写法:@testable
修改装饰器行为

装饰器自身只能接收一个参数target,如果觉得这样不够。可以在装饰器外面再封装一层函数。利用闭包

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


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

@testable(false)
class B {}
B.isTestable // false
修改状态时机

装饰器对类的行为修改,是在代码编译时发生的,而不是运行时

使用场景

React和Redux库结合使用时,常常需要以下方法

class Com extends React.Component {}

connect(mapStateToPros, mapDispatchToProps)(Com)

可以利用装饰器写成

@connect(mapStateToProps, mapDispatchToProps)
class Com extends React.Component {}

方法的装饰器

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

/**
装饰器函数
target: 类的原型对象,这个例子就是Person.prototype
name: 要装饰的属性名
descriptor:该属性的描述对象
*/
function readonly(target, name, descriptor) {
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

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

为什么不能用于函数

因为存在函数提升

core-decorators.js

core-decorators:一个第三方库,提供了一些装饰器