JavaScript 中的 Decorator

2016-12-21 Oliver Wang 更多博文 » 博客 » GitHub »

decorator js

原文链接 http://ochukai.me/decorator-in-js/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


昨天在看一个拖拽库的时候,遇到了这么一段代码,感觉很有意思:

@sortable
class DemoHOCItem extends React.Component {

  render() {
    return (
      <div { ...this.props }>
        { this.props.children }
      </div>
    );
  }

}

查了一下之后发现这是 es7 的新语法,叫 Decorator

语法

如果要定义一个 Decorator 的话,不难,其实每一个 decorator 就是一个 function,有三个参数,像这样

let log = (target, name, descriptor) => {
  console.log(target, name, descriptor);

  const method = descriptor.value;
  descriptor.value = (...args) => {
    logger.info(`before function execute: ${name}(${args}) = ?`);
    return method.apply(target, args);
  }
}

三个参数还是比较好理解的

然后要用这个 decorator 的时候

class Example {

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

}

let my = new Example();
my.add(2, 3);

这好像跟 Java 的 Annotation 形式差不多。 但是功能却跟 Python 的 Decorator 一样。

下面是运行时的输出

正常

所以呢,decorator 的三个参数分别是

  1. target 目标方法所在的类
  2. name 方法名
  3. descriptor 该方法的一些描述, 其中 value 就是方法本身,这一点在上一个例子中已经看到了。

用在 class 上面

因为我最开始见到 decorator 是看到

@sortable
class DemoHOCItem extends React.Component {/*...*/}

这时, decorator 是用在 class 上面的,当 decorator 用在 class 上面的时候只有第一个参数有值,比如

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

只会输出

# 也就是 name, descriptor 都是 undefined
2016-12-21 10:28:26.617 function Example() {
        _classCallCheck(this, Example);
    } undefined undefined