修饰类
target参数指的是,构造函数(类)Person,而不是实例。如果想对实例进行修饰,可以通过target.prototype对实例的属性进行修饰
const init = (target) => {
target.nickName = 'person_name'
target.prototype.nickName = 'kitty'
}
@init
class Person {
nickName = 'native_name'
}
const cat = new Person()
console.log('Person', Person.nickName) // 'Person person_name'
console.log('instance', cat.nickName) // 'instance native_name'
修饰方法
const log = (target, name, descriptor) => {
// 这里的this为undefined
const oldAdd = descriptor.value
descriptor.value = function(){
console.log(`传入实例方法add的参数${arguments}`)
console.log(`实例中的age属性:${this.age}`)
return oldAdd.apply(this, arguments)
}
return descriptor
}
class Math {
@log
add(a, b){
return a + b
}
}
var math = new Math()
const value = math.add(3, 6)
console.log(`value is equal to ${value}`)
结果为:
传入实例方法add的参数[object Arguments]
实例中的age属性:10
value is equal to 9
其中
descriptor.value = function(){
console.log(`传入实例方法add的参数${arguments}`)
console.log(`实例中的age属性:${this.age}`)
return oldAdd.apply(this, arguments)
}
this作用域为指向的是Math的实例math;当然this可以用target代替。
半透明的装饰模式(利用修饰类去修饰方法)
const addFly = (canFly) => {
return (target) => {
const extra = canFly ? '添加飞行技能' : ''
const old_toString = target.prototype.toString
target.prototype.toString = (...args) => {
// 这里的target只是指Man类,不能指向实例, 应该用targey.prototype指向实例
return old_toString.apply(target.prototype, args) + extra
}
}
}
@addFly(true)
class Man{
constructor(def = 2,atk = 3,hp = 3){
this.init(def,atk,hp)
}
@decorateArmour
@decorateLight
init(def,atk,hp){
this.def = def // 防御值
this.atk = atk // 攻击力
this.hp = hp // 血量
}
toString(){
return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`
}
}
通过引用函数的方式改变某个函数
在不改变函数源代码的情况下,能给函数增加功能,符合开放-封闭原则
let con = () => {
// 也可直接用function关键字来声明
console.log('old con')
}
const _con = con
con = () => {
_con()
console.log('new con')
}
con()
网友评论