class Person {@readonlyname() { return `${this.first} ${this.last}` }}
上面代码中,装饰器
readonly
用来装饰“类”的
name
方法。
装饰器函数
readonly
一共可以接受三个参数。
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);
装饰器第一个参数是类的原型对象,上例是
Person.prototype
,装饰器的本意是要“装饰”类的实例,但是这个时候实例还没生成,所以只能去装饰原型(这不同于类的装饰,那种情况时
target
参数指的是类本身);第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象。
另外,上面代码说明,装饰器(readonly)会修改属性的描述对象(descriptor),然后被修改的描述对象再用来定义属性。
下面是另一个例子,修改属性描述对象的
enumerable
属性,使得该属性不可遍历。
class Person { @nonenumerable get kidCount() { return this.children.length; }}function nonenumerable(target, name, descriptor) { descriptor.enumerable = false; return descriptor;}
下面的
@log
装饰器,可以起到输出日志的作用。
class Math { @log add(a, b) { return a + b; }}function log(target, name, descriptor) { var oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling ${name} with`, arguments); return oldValue.apply(this, arguments); }; return descriptor;}const math = new Math();// passed parameters should get logged nowmath.add(2, 4);
上面代码中,
@log
装饰器的作用就是在执行原始的操作之前,执行一次
console.log
,从而达到输出日志的目的。
装饰器有注释的作用。
@testableclass Person { @readonly @nonenumerable name() { return `${this.first} ${this.last}` }}
从上面代码中,我们一眼就能看出,
Person
类是可测试的,而
name
方法是只读和不可枚举的。
下面是使用 Decorator 写法的
组件
,看上去一目了然。
@Component({ tag: 'my-component', styleUrl: 'my-component.scss'})export class MyComponent { @Prop() first: string; @Prop() last: string; @State() isVisible: boolean = true; render() { return ( <p>Hello, my name is {this.first} {this.last}</p> ); }}
如果同一个方法有多个装饰器,会像剥洋葱一样,先从外到内进入,然后由内向外执行。
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)
先执行。
除了注释,装饰器还能用来类型检查。所以,对于类来说,这项功能相当有用。从长期来看,它将是 JavaScript 代码静态分析的重要工具。
-
ECMAScript 6 入门
-
0. 前言
-
1. ECMAScript 6 简介
-
2. let 和 const 命令
-
3. 变量的解构赋值
-
4. 字符串的扩展
-
5. 字符串的新增方法
-
6. 正则的扩展
-
7. 数值的扩展
-
8. 函数的扩展
-
9. 数组的扩展
-
10. 对象的扩展
-
11. 对象的新增方法
-
12. Symbol
-
13. Set 和 Map 数据结构
-
14. Proxy
-
15. Reflect
-
16. Promise 对象
-
17. Iterator 和 for…of 循环
-
18. Generator 函数的语法
-
19. Generator 函数的异步应用
-
20. async 函数
-
21. Class 的基本语法
-
22. Class 的继承
-
23. Module 的语法
-
24. Module 的加载实现
-
25. 编程风格
-
26. 读懂规格
-
27. 异步遍历器
-
28. ArrayBuffer
-
29. 最新提案
-
30. Decorator
-
31. 参考链接
-
32. Mixin
-
33. SIMD
-
34. 函数式编程
-
35. 鸣谢