装饰器
装饰器的本质是一个函数,只能作用类、类静态、动态成员。语义结构清晰,能够在不破坏类内聚的基础上,给类提供额外功能特性。装饰器在编译期会被转译为相应的表达式语句。
作用于类
@decorator
class Person {}
// 相当于
class Person {};
Person = decorator(Person) || Person;
作用于属性/方法
class Person {
@readonly
name() {}
}
// 相当于,装饰器的放回值仅充当 `descriptor` 的作用,忽略返回非 `descriptor`的属性
Object.defineProperty(Person.prototype, 'name', readonly(Person.prototype, 'name', Object.getOwnPropertyDescriptor(Person, 'name')) || Object.getOwnPropertyDescriptor(Person, 'name'));
装饰器可以接受参数
@decorator(true)
class Person {}
// 相当于
class Person {};
Person = decorator(true)(Person) || Person;
多个装饰器
// 作用于类
@dec(12)
@decorator(true)
class Person {}
// 相当于
class Person {};
// 执行顺序由外到内
const decFn = dec(12);
const decoratorFn = decorator(true)
// 执行顺序由内到外
Person = decoratorFn(Person) || Person;
Person = decFn(Person) || Person;
// 作用于属性/方法
class Person {
@readonly()
@override()
name() {}
}
// 相当于
class Person {};
// 执行顺序由外到内
const read = readonly();
const over = override()
// 执行顺序由内到外
let descriptor = Object.getOwnPropertyDescriptor(Person, 'name');
Object.defineProperty(Person.prototype, 'name', over(Person.prototype, 'name', descriptor) || descriptor);
descriptor = Object.getOwnPropertyDescriptor(Person, 'name');
Object.defineProperty(Person.prototype, 'name', read(Person.prototype, 'name', descriptor) || descriptor);
使用前准备
由于装饰器在目前还是一个提案,因此使用使用装饰器语法的时候 ,需要设置babel或typescript的相关配置。
-
babel需要安装语法支持插件[babel-plugin-syntax-decorators](https://www.npmjs.com/package/babel-plugin-syntax-decorators) -
typescript需要配置tsconfig.json{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true, // 配置使用装饰器语法 } }
第三方库
core-decorators.js,提供了几个常见的装饰器,部分如下:
- **@autobind**: `this`绑定
- **@readonly**:属性只读
- **@override**:覆盖原方法
- **@deprecate** (**@deprecated**):废弃标识
属性描述对象 说明
每个属性都有一个对应的属性描述对象 ,根据属性的不同可以分为数据属性或存取属性,相应的属性描述对象的结构也有所差别。通过Object.defineProperty 修改属性描述对象,能够实现数据属性于存取属性的相互转换。
| configurable(都有) | enumerable(都有) | value | ediatble | get | set | |
|---|---|---|---|---|---|---|
是否能修改属性描述对象(false时赋值表达式仍能修改value) | 属性是否能被枚举 | 属性的值 | 控制值能否被赋值表达式修改 | 属性读取时调用 | 属性赋值时调用 | |
| 数据属性 | 有 | 有 | 有 | 有 | 无 | 无 |
| 存取属性 | 有 | 有 | 无 | 无 | 有 | 有 |