# 装饰器
装饰器(decorator)最早在 Python 中被引入,它的主要作用是给一个已有的方法或类扩展一些新的行为,而不是去直接修改它本身.
在 ES2015 进入 Class 之后,当我们需要在多个不同的类之间共享或者扩展一些方法或行为的时候,代码会变得错综复杂,极其不优雅,这也就是装饰器被提出的一个很重要的原因.
但是推进比较缓慢,到目前为止也仅仅在 stage 2 阶段.

所以在 JavaScript 中我们需要 Babel 插件 babel-plugin-transform-decorators-legacy 来支持 decorator,而在 Typescript 中我们需要在 tsconfig.json 里面开启支持选项 experimentalDecorators.
// tsconfig.json
"experimentalDecorators": true
@前端进阶之旅: 代码已经复制到剪贴板
我们先明确两个概念:
- 目前装饰器本质上是一个函数,
@expression的形式其实是一个语法糖, expression 求值后必须也是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入. - JavaScript 中的 Class 其实也是一个语法糖,
比如在 JavaScript 中我们声明一个 Class:
class Person{
say() {
console.log('hello')
}
}
@前端进阶之旅: 代码已经复制到剪贴板
上面这个 Person 类实际上相当于:
function Person() {}
Object.defineProperty(Person.prototype, 'say', {
value: function() { console.log('hello'); },
enumerable: false,
configurable: true,
writable: true
});
@前端进阶之旅: 代码已经复制到剪贴板
# 类装饰器
比如,我们声明一个函数 addAge 去给 Class 的属性 age 添加年龄.
function addAge(constructor: Function) {
constructor.prototype.age = 18;
}
@addAge
class Person{
name: string;
age!: number;
constructor() {
this.name = 'xiaomuzhu';
}
}
let person = new Person();
console.log(person.age); // 18
@前端进阶之旅: 代码已经复制到剪贴板
所以这段代码实际上基本等同于:
Person = addAge(function Person() { ... });
@前端进阶之旅: 代码已经复制到剪贴板
当装饰器作为修饰类的时候,会把构造器传递进去。 constructor.prototype.age 就是在每一个实例化对象上面添加一个 age 值 这里我们的 addAge 就添加了一个 age 值.
