# Javascript装饰器模式
装饰器模式:在不改变原对象的基础上,通过对其进行包装拓展(添加属性或者方法)使原有对象可以满足用户的更复杂需求。
# 实现
function fn1() {
console.log('fn1 by call');
}
function fn2() {
console.log('fn2 by call');
}
function fn3() {
console.log('fn3 by call');
}
现在需要一个对调用方法名字的打印。
function fn1() {
console.log(fn1.name);
console.log('fn1 by call');
}
function fn2() {
console.log(fn2.name);
console.log('fn2 by call');
}
function fn3() {
console.log(fn3.name);
console.log('fn3 by call');
}
f1();
// fn1
// fn1 by call
f2();
// fn2
// fn2 by call
f3();
// fn3
// fn3 by call
更简单的写法:
// 装饰器:方法执行前包装一层
function decorator(fn) {
console.log(fn.name);
fn();
}
decorator(fn1);
decorator(fn2);
decorator(fn3);
// fn1
// fn1 by call
// fn2
// fn2 by call
// fn3
// fn3 by call
这是一种可以在不了解原有功能的基础上对功能拓展模式,这是对原有功能的一种增强与拓展。
# 装饰类
class MyClass {
}
/**
* 对target添加一个静态属性
* @param {class} 需要操作的类
*/
function testable(target) {
target.isTestable = true;
}
testable(MyClass);
console.log(MyClass.isTestable); // true
# 装饰类的属性
class MyClass {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
function readonly(target, name, descriptor = {}){
descriptor.writable = false;
Object.defineProperty(target, name, descriptor);
}
let cls = new MyClass('abc'); // abc
// 定义属性只读
readonly(MyClass.prototype, 'name');
let cls = new MyClass('bca'); // 抛出错误 this.name不可修改