什么是装饰器
装饰器(decorator)是一种函数,用于注释或修改类、类方法。写成@ + 函数名
除了注释,装饰器还能用来类型检查。所以,对于类来说,这项功能相当有用。从长期来看,它将是 JavaScript 代码静态分析的重要工具
类的装饰
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
@testable就是一个装饰器,它修改了Foo这个类的行为,为它加上了静态属性isTestable
function testable(target) {
target.isTestable = true;
}
@testable
class Foo{}
console.log(Foo.isTestable);
装饰器还可以传递参数
function testable(isTestable) {
return function(target){
target.isTestable = isTestable;
}
}
@testable(false)
class Foo{}
注意:装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。
方法的装饰
装饰器第一个参数是类的原型对象,第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象
function readonly(target, name, descriptor){
// descriptor对象原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writeable: true,
// }
descriptor.writeable = false;
return descriptor;
}
function log(target, name, descriptor){
const oldValue = descriptor.value;
descriptor.value = function () {
return oldValue.apply(this, arguments);
}
return descriptor;
}
class Foo{
@readonly
name() {
return 'this is name';
}
@log
add(a, b) {
return a + b;
}
}
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);
为什么装饰器不能用于函数
装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升
var counter = 0;
var add = function () {
counter++;
};
@add
function foo() {
}
//
@add
function foo() {
}
var counter;
var add;
counter = 0;
add = function () {
counter++;
};
总之,由于存在函数提升,使得装饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。