什么是Decorator
Decorator
是修饰器,用来修饰类的行为,它是ES7的一个实现,目前Babel转码器已经支持。
修饰器的使用
修饰器对类的行为的改变,是发生在代码编译时的。修饰器也只能对类以及类的属性使用。
修饰类
function testable(target) {
target.isTestable = true;
}
@testable
class MyTestableClass {}
console.log(MyTestableClass.isTestable) // true
最简化来看:
@decorator
class A {}
// 等同于以下行为
class A {}
A = decorator(A) || A;
也就是说,修饰器本质就是编译时对target
执行的函数。
类修饰器的第一个参数target
,就是要修饰的目标类。同时,因为修饰器只是函数,所以可以使用执行的函数,而不是函数指针,只要最后有一个接受target
的函数修饰类就可以了:
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true) //执行testable后是返回函数指针
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
现在都是添加静态属性,如果想添加实例属性,就只能添加到target
的原型(prototype)上了:
function testable(target) {
target.prototype.isTestable = true;
}
@testable
class MyTestableClass {}
let obj = new MyTestableClass();
obj.isTestable // true
这里会有个问题!!!!!!!!
修饰属性
修饰属性时修饰函数一共接受三个参数,第一个参数是所要修饰的目标对象(ClassName.prototype
),第二个参数是所要修饰的属性,第三个参数是该属性的描述对象,还有一点,修饰属性时需要返回描述对象:
function readonly(target, name, descriptor){
descriptor.writable = false;
return descriptor;
}
class Person {
@readonly
name() { return "Person" }
}
以上Person
实例的name
方法就是只读的了。
对value
的修改可以实现输出日志的作用:
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(null, arguments); //最后再调用旧方法获得执行的结果
};
return descriptor;
}
const math = new Math();
// passed parameters should get logged now
math.add(2, 4);